[インデックス 13754] ファイルの概要
このコミットは、Goコンパイラの内部定数(オペレーションコード、通称 OFOO
定数)の整理とリファクタリングに関するものです。具体的には、一部の定数の順序変更、ORRC
定数の ORROTC
への名称変更、および未使用の OBAD
と OLRC
定数の削除が行われています。これにより、コンパイラのコードベースの整合性と保守性が向上しています。
コミット
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
)の内部コードの整理と改善です。具体的には以下の点が挙げられます。
- 定数の整合性向上:
ORRC
(Rotate Right with Carry) というオペレーションコードが、既存のOLROT
(Rotate Left) との命名規則の整合性を保つためにORROTC
(Rotate Right with Carry) に変更されました。これにより、関連する操作の命名が一貫し、コードの可読性が向上します。 - 未使用コードの削除:
OBAD
およびOLRC
というオペレーションコードが、コンパイラ内で実際には使用されていないことが判明したため、削除されました。これにより、デッドコードが排除され、コードベースがスリム化され、将来的なメンテナンスの負担が軽減されます。 - 定数の論理的な再配置: 一部のオペレーションコード(特に
OHMUL
、ORROTC
)が、より適切なカテゴリ、すなわち「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アーキテクチャの ROL
や RCR
命令)に対応するために使用されます。
src/cmd/6g
src/cmd/6g
は、Goコンパイラのx86-64アーキテクチャ(AMD64)向けのバックエンドの一部です。Goコンパイラは、異なるアーキテクチャ(例: 6g
for amd64, 8g
for arm, 5g
for arm64など)に対応するために、それぞれ異なるバックエンドを持っています。ggen.c
や gsubr.c
のようなファイルは、これらのバックエンドにおけるコード生成やサブルーチン処理を担当します。
技術的詳細
このコミットの技術的詳細は、Goコンパイラの内部構造、特にオペレーションコードの管理とコード生成の側面に関わっています。
-
OFOO
定数の再配置:src/cmd/gc/go.h
ファイルにおいて、enum
で定義されているオペレーションコードの順序が変更されました。特に、OHMUL
(High Multiply) とORRC
(Rename後のORROTC
) は、以前は汎用的なオペレーションコードのセクションに置かれていましたが、このコミットで「386/amd64-specific opcodes」という新しいセクションに移動されました。これは、これらの操作がx86/x64アーキテクチャの特定のCPU命令(AMUL
/AIMUL
やARCR
)に直接対応しており、他のアーキテクチャでは異なる実装が必要となるか、あるいは存在しない可能性があるためです。このような分類は、コンパイラのクロスプラットフォーム対応を容易にし、アーキテクチャ固有のコードを明確に分離するのに役立ちます。 -
ORRC
からORROTC
への名称変更:ORRC
は "Rotate Right with Carry" を意味するオペレーションコードでしたが、既存の "Rotate Left" を意味するOLROT
との命名規則の整合性を取るためにORROTC
に変更されました。この変更は、主にsrc/cmd/6g/ggen.c
とsrc/cmd/6g/gsubr.c
の2つのファイルに影響を与えました。ggen.c
は、Goコンパイラのコードジェネレータの一部であり、中間表現からアセンブリコードを生成する際にこれらのオペレーションコードを使用します。divbymul
というラベルの付いたセクションで、ORRC
がORROTC
に置き換えられています。これは、除算の最適化ルーチンにおいて、キャリー付き右ローテーション操作が使用されていることを示唆しています。gsubr.c
は、Goコンパイラのサブルーチンを扱うファイルで、optoas
関数内でORRC
に関連するCASE
文がORROTC
に変更されています。optoas
関数は、Goのオペレーションコードをアセンブリ命令(例:ARCRB
,ARCRW
,ARCRL
,ARCRQ
はそれぞれ8ビット、16ビット、32ビット、64ビットのキャリー付き右ローテーション命令に対応)にマッピングする役割を担っています。この変更により、コンパイラが正しいアセンブリ命令を生成するようになります。
-
OBAD
およびOLRC
の削除:src/cmd/gc/go.h
からOBAD
とOLRC
の2つのオペレーションコードが削除されました。OBAD
はコメントで "unused" と明記されており、コンパイラの開発過程で一時的に導入されたものの、最終的に使用されなかったか、あるいは別の方法で処理されるようになった定数であると考えられます。OLRC
も同様に "unused" とコメントされており、"left rotate-carry" を意味する可能性のある操作ですが、実際には使用されていなかったため削除されました。 これらの削除は、コードベースの冗長性を減らし、コンパイラのフットプリントを小さくするのに貢献します。
これらの変更は、Goコンパイラの内部的な整合性を高め、将来的な機能追加や最適化のための基盤を強化するものです。特に、オペレーションコードの明確な分類と命名規則の統一は、コンパイラの複雑なコードベースを管理する上で非常に重要です。
コアとなるコードの変更箇所
このコミットにおける主要なコード変更は、以下の3つのファイルに集中しています。
-
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
という除算最適化ルーチン内で使用されている部分です。 -
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アセンブリ命令へのマッピングが更新されます。 -
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, };
OBAD
とOLRC
が削除されています。OHMUL
とORRC
(変更後はORROTC
) が、// TODO: move these to the "for back ends" section, like OLROT.
というコメントのあった場所から、新しく追加された// 386/amd64-specific opcodes
セクションに移動されています。ORRC
がORROTC
に名称変更されています。
コアとなるコードの解説
このコミットのコアとなる変更は、Goコンパイラの内部で使われるオペレーションコードの定義と、それがアセンブリ命令にマッピングされる方法にあります。
src/cmd/gc/go.h
は、Goコンパイラが使用するすべての主要なオペレーションコードを定義するヘッダーファイルです。これらのオペレーションコードは、コンパイラのフロントエンドがGoのソースコードを解析して中間表現を構築する際に使用されます。このファイルでの変更は、コンパイラの内部的な語彙を直接変更するものです。
-
OBAD
とOLRC
の削除: これらの定数が削除されたことは、コンパイラのコードベースから未使用の定義が取り除かれたことを意味します。これは、コードの肥大化を防ぎ、コンパイラの理解と保守を容易にするための一般的なクリーンアップ作業です。未使用のコードは、誤解を招いたり、将来的に誤って使用されたりするリスクがあるため、削除することが推奨されます。 -
ORRC
からORROTC
への名称変更と定数の再配置:ORRC
は、"Rotate Right with Carry" を表すオペレーションコードでした。この操作は、CPUのキャリーフラグを含めてビットを右に循環シフトするもので、特に多倍長整数演算や暗号化アルゴリズムなどで利用されることがあります。OLROT
は、"Rotate Left" を表すオペレーションコードです。- このコミットでは、
ORRC
がORROTC
に名称変更されました。これは、OLROT
との命名規則の整合性を図るためです。OLROT
のROT
が "Rotate" を意味するように、ORROTC
のROTC
も "Rotate with Carry" を明確に示します。このような一貫した命名は、開発者がオペレーションコードの機能を直感的に理解するのに役立ちます。 - さらに、
OHMUL
(High Multiply) とORROTC
は、// 386/amd64-specific opcodes
という新しいセクションに移動されました。これは、これらのオペレーションが特定のCPUアーキテクチャ(この場合はx86/x64)に特有の命令(AMUL
/AIMUL
やARCR
)に直接マッピングされるためです。コンパイラは、ターゲットアーキテクチャに応じて異なるコード生成戦略を取るため、アーキテクチャ固有のオペレーションコードを明確に分離することは、コンパイラのモジュール性と拡張性を高めます。
src/cmd/6g/ggen.c
と src/cmd/6g/gsubr.c
は、Goコンパイラのx86/x64バックエンドの一部であり、実際に機械語を生成する段階でこれらのオペレーションコードを扱います。
-
ggen.c
での変更は、コンパイラが中間表現からアセンブリコードを生成する際に、新しいオペレーションコード名ORROTC
を使用するように更新されたことを示しています。これは、コンパイラのコード生成ロジックが、go.h
で定義された新しい定数名と同期していることを保証します。 -
gsubr.c
のoptoas
関数での変更は、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 Compiler Design: https://go.dev/doc/compiler (これはより現代のコンパイラに関するものですが、基本的な概念は役立ちます)
- Go Source Code: https://go.dev/src/
参考にした情報源リンク
- 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のコードレビューシステムへのリンクです。