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

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

このコミットは、Goコンパイラの内部定数(オペレーションコード、通称 OFOO 定数)の整理とリファクタリングに関するものです。具体的には、一部の定数の順序変更、ORRC 定数の ORROTC への名称変更、および未使用の OBADOLRC 定数の削除が行われています。これにより、コンパイラのコードベースの整合性と保守性が向上しています。

コミット

commit 481e5c6ad05fa6e43f4df10a372a775486ec14c2
Author: Nigel Tao <nigeltao@golang.org>
Date:   Thu Sep 6 10:47:25 2012 +1000

    cmd/gc: re-order some OFOO constants. Rename ORRC to ORROTC to be
    consistent with OLROT. Delete unused OBAD, OLRC.
    
    R=rsc, dave
    CC=golang-dev
    https://golang.org/cl/6489082

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

https://github.com/golang/go/commit/481e5c6ad05fa6e43f4df10a372a775486ec14c2

元コミット内容

cmd/gc: re-order some OFOO constants. Rename ORRC to ORROTC to be
consistent with OLROT. Delete unused OBAD, OLRC.

変更の背景

このコミットの主な背景は、Goコンパイラ(cmd/gc)の内部コードの整理と改善です。具体的には以下の点が挙げられます。

  1. 定数の整合性向上: ORRC (Rotate Right with Carry) というオペレーションコードが、既存の OLROT (Rotate Left) との命名規則の整合性を保つために ORROTC (Rotate Right with Carry) に変更されました。これにより、関連する操作の命名が一貫し、コードの可読性が向上します。
  2. 未使用コードの削除: OBAD および OLRC というオペレーションコードが、コンパイラ内で実際には使用されていないことが判明したため、削除されました。これにより、デッドコードが排除され、コードベースがスリム化され、将来的なメンテナンスの負担が軽減されます。
  3. 定数の論理的な再配置: 一部のオペレーションコード(特に OHMULORROTC)が、より適切なカテゴリ、すなわち「386/amd64-specific opcodes」セクションに移動されました。これは、これらの操作が特定のアーキテクチャに特化していることを明確にし、定数の定義がより論理的に整理されることを意味します。

これらの変更は、コンパイラの内部構造をよりクリーンで理解しやすいものにし、長期的な開発と保守を容易にすることを目的としています。

前提知識の解説

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

Goコンパイラ (cmd/gc)

Go言語の公式コンパイラは、主に cmd/gc と呼ばれるツールチェーンの一部です。これは、Goのソースコードを機械語に変換する役割を担っています。コンパイラは、ソースコードの字句解析、構文解析、意味解析、中間表現の生成、最適化、そして最終的なコード生成といった複数のフェーズを経て動作します。

オペレーションコード (OFOO定数)

Goコンパイラの内部では、プログラムの各操作(例えば、加算、乗算、関数呼び出し、変数への代入など)を表現するために、独自の「オペレーションコード」(略して OFOO 定数、O は "Opcode" を意味することが多い)が定義されています。これらは、コンパイラがソースコードを解析して生成する抽象構文木(AST)や中間表現(IR)のノードの種類を識別するために使用されます。例えば、OADD は加算、OMUL は乗算を表します。これらの定数は、通常、go.h のようなヘッダーファイルで enum として定義されています。

ビット演算とローテーション操作

ビット演算は、数値の個々のビットに対して直接操作を行うことです。ローテーション操作は、ビット列を循環的にシフトする操作です。

  • 左ローテーション (Rotate Left): ビット列を左にシフトし、左端からあふれたビットを右端に戻します。
  • 右ローテーション (Rotate Right): ビット列を右にシフトし、右端からあふれたビットを左端に戻します。
  • キャリー付きローテーション (Rotate with Carry): 通常のローテーションに加えて、CPUのキャリーフラグ(前の演算で発生した桁上がりや桁借りを示すフラグ)もローテーションの一部として含める操作です。これは、多倍長整数演算などで利用されることがあります。

OLROT は左ローテーション、ORRC (または ORROTC) はキャリー付き右ローテーションを表します。これらは、低レベルのコード生成において、特定のCPU命令(例えば、x86/x64アーキテクチャの ROLRCR 命令)に対応するために使用されます。

src/cmd/6g

src/cmd/6g は、Goコンパイラのx86-64アーキテクチャ(AMD64)向けのバックエンドの一部です。Goコンパイラは、異なるアーキテクチャ(例: 6g for amd64, 8g for arm, 5g for arm64など)に対応するために、それぞれ異なるバックエンドを持っています。ggen.cgsubr.c のようなファイルは、これらのバックエンドにおけるコード生成やサブルーチン処理を担当します。

技術的詳細

このコミットの技術的詳細は、Goコンパイラの内部構造、特にオペレーションコードの管理とコード生成の側面に関わっています。

  1. OFOO 定数の再配置: src/cmd/gc/go.h ファイルにおいて、enum で定義されているオペレーションコードの順序が変更されました。特に、OHMUL (High Multiply) と ORRC (Rename後の ORROTC) は、以前は汎用的なオペレーションコードのセクションに置かれていましたが、このコミットで「386/amd64-specific opcodes」という新しいセクションに移動されました。これは、これらの操作がx86/x64アーキテクチャの特定のCPU命令(AMUL/AIMULARCR)に直接対応しており、他のアーキテクチャでは異なる実装が必要となるか、あるいは存在しない可能性があるためです。このような分類は、コンパイラのクロスプラットフォーム対応を容易にし、アーキテクチャ固有のコードを明確に分離するのに役立ちます。

  2. ORRC から ORROTC への名称変更: ORRC は "Rotate Right with Carry" を意味するオペレーションコードでしたが、既存の "Rotate Left" を意味する OLROT との命名規則の整合性を取るために ORROTC に変更されました。この変更は、主に src/cmd/6g/ggen.csrc/cmd/6g/gsubr.c の2つのファイルに影響を与えました。

    • ggen.c は、Goコンパイラのコードジェネレータの一部であり、中間表現からアセンブリコードを生成する際にこれらのオペレーションコードを使用します。divbymul というラベルの付いたセクションで、ORRCORROTC に置き換えられています。これは、除算の最適化ルーチンにおいて、キャリー付き右ローテーション操作が使用されていることを示唆しています。
    • gsubr.c は、Goコンパイラのサブルーチンを扱うファイルで、optoas 関数内で ORRC に関連する CASE 文が ORROTC に変更されています。optoas 関数は、Goのオペレーションコードをアセンブリ命令(例: ARCRB, ARCRW, ARCRL, ARCRQ はそれぞれ8ビット、16ビット、32ビット、64ビットのキャリー付き右ローテーション命令に対応)にマッピングする役割を担っています。この変更により、コンパイラが正しいアセンブリ命令を生成するようになります。
  3. OBAD および OLRC の削除: src/cmd/gc/go.h から OBADOLRC の2つのオペレーションコードが削除されました。

    • OBAD はコメントで "unused" と明記されており、コンパイラの開発過程で一時的に導入されたものの、最終的に使用されなかったか、あるいは別の方法で処理されるようになった定数であると考えられます。
    • OLRC も同様に "unused" とコメントされており、"left rotate-carry" を意味する可能性のある操作ですが、実際には使用されていなかったため削除されました。 これらの削除は、コードベースの冗長性を減らし、コンパイラのフットプリントを小さくするのに貢献します。

これらの変更は、Goコンパイラの内部的な整合性を高め、将来的な機能追加や最適化のための基盤を強化するものです。特に、オペレーションコードの明確な分類と命名規則の統一は、コンパイラの複雑なコードベースを管理する上で非常に重要です。

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

このコミットにおける主要なコード変更は、以下の3つのファイルに集中しています。

  1. src/cmd/6g/ggen.c:

    --- a/src/cmd/6g/ggen.c
    +++ b/src/cmd/6g/ggen.c
    @@ -758,7 +758,7 @@ divbymul:
     			// need to add numerator accounting for overflow
     			gins(optoas(OADD, nl->type), &n1, &dx);\
     			nodconst(&n2, nl->type, 1);\
    -			gins(optoas(ORRC, nl->type), &n2, &dx);\
    +			gins(optoas(ORROTC, nl->type), &n2, &dx);\
     			nodconst(&n2, nl->type, m.s-1);\
     			gins(optoas(ORSH, nl->type), &n2, &dx);\
     		} else {
    

    ORRC オペレーションコードが ORROTC に変更されています。これは、divbymul という除算最適化ルーチン内で使用されている部分です。

  2. src/cmd/6g/gsubr.c:

    --- a/src/cmd/6g/gsubr.c
    +++ b/src/cmd/6g/gsubr.c
    @@ -1724,23 +1724,23 @@ optoas(int op, Type *t)
     		a = ASARQ;
     		break;
     
    -	case CASE(ORRC, TINT8):
    -	case CASE(ORRC, TUINT8):
    +	case CASE(ORROTC, TINT8):
    +	case CASE(ORROTC, TUINT8):
     		a = ARCRB;
     		break;
     
    -	case CASE(ORRC, TINT16):
    -	case CASE(ORRC, TUINT16):
    +	case CASE(ORROTC, TINT16):
    +	case CASE(ORROTC, TUINT16):
     		a = ARCRW;
     		break;
     
    -	case CASE(ORRC, TINT32):
    -	case CASE(ORRC, TUINT32):
    +	case CASE(ORROTC, TINT32):
    +	case CASE(ORROTC, TUINT32):
     		a = ARCRL;
     		break;
     
    -	case CASE(ORRC, TINT64):
    -	case CASE(ORRC, TUINT64):
    +	case CASE(ORROTC, TINT64):
    +	case CASE(ORROTC, TUINT64):
     		a = ARCRQ;
     		break;
     
    

    optoas 関数内で、ORRC を処理する case 文がすべて ORROTC に変更されています。これにより、Goのオペレーションコードから対応するx86/x64アセンブリ命令へのマッピングが更新されます。

  3. src/cmd/gc/go.h:

    --- a/src/cmd/gc/go.h
    +++ b/src/cmd/gc/go.h
    @@ -431,7 +431,6 @@ enum
     	OAS2MAPR,	// x, ok = m["foo"]
     	OAS2DOTTYPE,	// x, ok = I.(int)
     	OASOP,	// x += y
    -	OBAD,	// unused.
     	OCALL,	// function call, method call or type conversion, possibly preceded by defer or go.
     	OCALLFUNC,	// f()
     	OCALLMETH,	// t.Method()
    @@ -479,12 +478,6 @@ enum
     	OMAKECHAN,	// make(chan int)
     	OMAKEMAP,	// make(map[string]int)
     	OMAKESLICE,	// make([]int, 0)
    -
    -	// TODO: move these to the "for back ends" section, like OLROT.
    -	OHMUL, // high-mul. 386/amd64: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).
    -	ORRC, // right rotate-carry. 386/amd64: ARCR.
    -	OLRC, // unused.
    -
     	OMUL,	// x * y
     	ODIV,	// x / y
     	OMOD,	// x % y
    @@ -553,14 +546,18 @@ enum
     	OEFACE,	// itable and data words of an empty-interface value.
     	OITAB,	// itable word of an interface value.
     
    -	// for back ends
    -	OCMP,	// compare. 386/amd64: ACMP.
    -	ODEC,	// decrement. 386/amd64: ADEC.
    -	OEXTEND,	// extend. 386/amd64: ACWD/ACDQ/ACQO.
    -	OINC,	// increment. 386/amd64: AINC.
    -	OREGISTER,	// an arch-specific register.
    +	// arch-specific registers
    +	OREGISTER,	// a register, such as AX.
     	OINDREG,	// offset plus indirect of a register, such as 8(SP).
    -	OLROT,	// rotate left. 386/amd64: AROL.
    +\
    +	// 386/amd64-specific opcodes
    +	OCMP,	// compare: ACMP.
    +	ODEC,	// decrement: ADEC.
    +	OINC,	// increment: AINC.
    +	OEXTEND,	// extend: ACWD/ACDQ/ACQO.
    +	OHMUL, // high mul: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).\
    +	OLROT,	// left rotate: AROL.\
    +	ORROTC, // right rotate-carry: ARCR.\
     
     	OEND,
      };
    
    • OBADOLRC が削除されています。
    • OHMULORRC (変更後は ORROTC) が、// TODO: move these to the "for back ends" section, like OLROT. というコメントのあった場所から、新しく追加された // 386/amd64-specific opcodes セクションに移動されています。
    • ORRCORROTC に名称変更されています。

コアとなるコードの解説

このコミットのコアとなる変更は、Goコンパイラの内部で使われるオペレーションコードの定義と、それがアセンブリ命令にマッピングされる方法にあります。

src/cmd/gc/go.h は、Goコンパイラが使用するすべての主要なオペレーションコードを定義するヘッダーファイルです。これらのオペレーションコードは、コンパイラのフロントエンドがGoのソースコードを解析して中間表現を構築する際に使用されます。このファイルでの変更は、コンパイラの内部的な語彙を直接変更するものです。

  • OBADOLRC の削除: これらの定数が削除されたことは、コンパイラのコードベースから未使用の定義が取り除かれたことを意味します。これは、コードの肥大化を防ぎ、コンパイラの理解と保守を容易にするための一般的なクリーンアップ作業です。未使用のコードは、誤解を招いたり、将来的に誤って使用されたりするリスクがあるため、削除することが推奨されます。

  • ORRC から ORROTC への名称変更と定数の再配置:

    • ORRC は、"Rotate Right with Carry" を表すオペレーションコードでした。この操作は、CPUのキャリーフラグを含めてビットを右に循環シフトするもので、特に多倍長整数演算や暗号化アルゴリズムなどで利用されることがあります。
    • OLROT は、"Rotate Left" を表すオペレーションコードです。
    • このコミットでは、ORRCORROTC に名称変更されました。これは、OLROT との命名規則の整合性を図るためです。OLROTROT が "Rotate" を意味するように、ORROTCROTC も "Rotate with Carry" を明確に示します。このような一貫した命名は、開発者がオペレーションコードの機能を直感的に理解するのに役立ちます。
    • さらに、OHMUL (High Multiply) と ORROTC は、// 386/amd64-specific opcodes という新しいセクションに移動されました。これは、これらのオペレーションが特定のCPUアーキテクチャ(この場合はx86/x64)に特有の命令(AMUL/AIMULARCR)に直接マッピングされるためです。コンパイラは、ターゲットアーキテクチャに応じて異なるコード生成戦略を取るため、アーキテクチャ固有のオペレーションコードを明確に分離することは、コンパイラのモジュール性と拡張性を高めます。

src/cmd/6g/ggen.csrc/cmd/6g/gsubr.c は、Goコンパイラのx86/x64バックエンドの一部であり、実際に機械語を生成する段階でこれらのオペレーションコードを扱います。

  • ggen.c での変更は、コンパイラが中間表現からアセンブリコードを生成する際に、新しいオペレーションコード名 ORROTC を使用するように更新されたことを示しています。これは、コンパイラのコード生成ロジックが、go.h で定義された新しい定数名と同期していることを保証します。

  • gsubr.coptoas 関数での変更は、Goの内部オペレーションコードを、実際のCPUアセンブリ命令にマッピングする部分です。optoas は "Opcode to Assembly" の略であり、Goの抽象的な操作を、ターゲットアーキテクチャの具体的な命令に変換する役割を担います。ORRC に対応していた case 文が ORROTC に変更されたことで、コンパイラは ORROTC オペレーションコードに対して、正しいx86/x64のキャリー付き右ローテーション命令(ARCRB, ARCRW, ARCRL, ARCRQ)を生成するようになります。これらの命令は、それぞれ8ビット、16ビット、32ビット、64ビットのオペランドに対応しています。

これらの変更は、Goコンパイラの内部的な整合性を高め、コードベースの保守性を向上させるための重要なステップです。特に、オペレーションコードの命名規則の統一と、アーキテクチャ固有の操作の明確な分離は、コンパイラの長期的な健全性を保つ上で不可欠です。

関連リンク

  • Go言語の公式リポジトリ: https://github.com/golang/go
  • Goコンパイラの内部構造に関するドキュメント(Goのバージョンによって異なる可能性がありますが、一般的な概念は共通です):

参考にした情報源リンク

  • Go言語のソースコード (特に src/cmd/gc/go.h, src/cmd/6g/ggen.c, src/cmd/6g/gsubr.c)
  • Gitコミット履歴と差分情報
  • Go言語のコンパイラに関する一般的な知識
  • x86/x64アセンブリ言語のビット演算命令に関する知識 (ROL, ROR, RCL, RCRなど)
  • Go言語の公式ドキュメント
  • Go言語のIssueトラッカーやコードレビューシステム (CL: Change List) - コミットメッセージに記載されている https://golang.org/cl/6489082 は、この変更に関するGoのコードレビューシステムへのリンクです。