[インデックス 18358] ファイルの概要
このコミットは、Go言語の初期のAMD64 (x86-64) アセンブラである cmd/6a
に、MOVQL
という新しいオペコード(命令コード)を追加するものです。これは、アセンブラが特定の命令を正しく認識し、処理できるようにするための字句解析器の更新です。
コミット
- コミットハッシュ:
ea86752206fd8801bce46cc21a0faf97d8d7cd01
- Author: Keith Randall khr@golang.org
- Date: Mon Jan 27 11:17:12 2014 -0800
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ea86752206fd8801bce46cc21a0faf97d8d7cd01
元コミット内容
cmd/6a: include MOVQL opcode.
LGTM=r
R=golang-codereviews, r
CC=golang-codereviews
https://golang.org/cl/54660046
変更の背景
この変更は、Go言語のコンパイラツールチェーンの一部である cmd/6a
アセンブラが、MOVQL
という特定の命令を認識できるようにするために行われました。cmd/6a
は、Go 1.5で cmd/asm
に置き換えられる前の、Go言語の初期のAMD64 (x86-64) アーキテクチャ向けアセンブラです。
x86-64アーキテクチャにおいて、64ビットのデータを移動する標準的な命令は MOVQ
です。MOVQL
という命令は標準的なx86-64命令セットには存在しません。これは、Goアセンブラが持つ「半抽象的な命令セット」の一部である可能性が高いです。Goアセンブラは、直接的な機械語命令ではなく、より抽象化された命令を扱います。これにより、コンパイラが最終的な機械語を生成する際に、より柔軟な最適化(例えば、MOV
命令を clear
や load
命令に最適化するなど)を行うことができます。
したがって、このコミットの背景には、Goコンパイラまたはランタイムの内部的なコード生成ロジックが MOVQL
という概念を使用しており、それをアセンブラが正しく字句解析できるようにする必要があったという事情が考えられます。これは、特定の最適化パスや、特定のデータ型(例えば、long long
や quadword
に対応するGoの型)の処理に関連している可能性があります。
前提知識の解説
Goアセンブラ (cmd/6a
)
Go言語は高水準言語ですが、ランタイムのブートストラップ、スタック管理、コンテキストスイッチなどの低レベルな操作、あるいはパフォーマンスが重要な特定のライブラリ(例: math/big
)ではアセンブリコードが使用されます。
- 歴史的背景: Go言語の初期のバージョンでは、Plan 9オペレーティングシステム由来のアセンブラが使用されていました。
6a
はAMD64 (x86-64) アーキテクチャ用、8a
は386アーキテクチャ用でした。これらはC言語で書かれた独立したプログラムでした。 - 半抽象的な命令セット: Goアセンブラの重要な特徴は、それが直接的な機械語命令を表現するのではなく、半抽象的な命令セットで動作する点です。例えば、
MOV
命令は常に直接的な機械語のMOV
命令に対応するわけではなく、ツールチェーンによってclear
やload
命令に最適化されることがあります。命令選択はコード生成の後に行われる部分もあります。 cmd/asm
への移行: Go 1.5以降、アセンブラは完全にGo言語で書き直され、cmd/asm
としてGoツールチェーンの一部となりました。この新しいアセンブラは、共通の字句解析器とパーサーを持ち、よりテーブル駆動型になっています。
x86-64のMOV命令
x86-64アーキテクチャにおける MOV
命令は、データをソースオペランドからデスティネーションオペランドへ転送するために使用されます。オペランドのサイズは、MOV
に付加されるサフィックスによって示されます。
MOVB
: 1バイト (byte)MOVW
: 2バイト (word)MOVL
: 4バイト (doubleword)MOVQ
: 8バイト (quadword)
MOVQL
という命令は、標準的なx86-64命令セットには存在しません。これは、Goアセンブラの内部的な表現、または特定のコンテキストでのみ使用される擬似命令である可能性が高いです。
字句解析 (Lexical Analysis)
字句解析(レキシングまたはスキャニングとも呼ばれる)は、コンパイラやアセンブラの最初のフェーズです。その主な役割は、ソースコードを文字単位で読み込み、それらを意味のあるまとまりである「トークン」にグループ化することです。トークンは、言語の基本的な構成要素(キーワード、識別子、演算子、リテラル、句読点など)を表します。
アセンブラの文脈では、字句解析器はアセンブリコードを読み込み、MOVQ
のような命令、AX
のようなレジスタ、ラベル、定数などをトークンとして識別します。src/cmd/6a/lex.c
のようなファイルは、この字句解析のロジックを実装しており、アセンブラが認識すべき命令やシンボルを定義しています。
技術的詳細
このコミットは、src/cmd/6a/lex.c
ファイルに MOVQL
という文字列とそれに対応する内部定数 AMOVQL
を追加することで、cmd/6a
アセンブラの字句解析器を更新しています。
lex.c
ファイルは、アセンブラがソースコードを読み込む際に、どの文字列がどの命令やシンボルに対応するかを定義するテーブルを含んでいます。このテーブルは通常、文字列(命令のニーモニック)、そのタイプ(例: LTYPE3
)、そして対応する内部的なアセンブラ命令コード(例: AMOVQL
)の組み合わせで構成されます。
"MOVQL"
: これは、アセンブリソースコード内でMOVQL
という文字列が出現したときに、アセンブラがそれを特定の命令として認識するためのニーモニックです。LTYPE3
: これは、MOVQL
命令のタイプまたはカテゴリを示す内部的な定数です。Goアセンブラの内部では、命令がどのように引数を取るか、またはどのような特性を持つかによって分類されています。LTYPE3
は、おそらく3つのオペランドを持つ命令、または特定の種類のオペランドを期待する命令を示すものと考えられます。AMOVQL
: これは、MOVQL
命令に対応するアセンブラの内部的な命令コード(opcode)です。字句解析器がMOVQL
を認識すると、このAMOVQL
という内部コードに変換され、後続のパーシングやコード生成フェーズで利用されます。
MOVQL
が標準のx86-64命令ではないことから、これはGoコンパイラが特定の最適化や内部処理のために生成する、Goアセンブラ独自の擬似命令である可能性が高いです。例えば、Goの int64
型や uint64
型の変数を特定のレジスタやメモリ位置に移動する際に、コンパイラが MOVQL
を出力し、それを 6a
アセンブラが処理するように設計されていたのかもしれません。
コアとなるコードの変更箇所
--- a/src/cmd/6a/lex.c
+++ b/src/cmd/6a/lex.c
@@ -507,6 +507,7 @@ struct
"MOVLQZX", LTYPE3, AMOVLQZX,
"MOVNTIL", LTYPE3, AMOVNTIL,
"MOVNTIQ", LTYPE3, AMOVNTIQ,
+ "MOVQL", LTYPE3, AMOVQL,
"MOVWLSX", LTYPE3, AMOVWLSX,
"MOVWLZX", LTYPE3, AMOVWLZX,
"MOVWQSX", LTYPE3, AMOVWQSX,
コアとなるコードの解説
変更は src/cmd/6a/lex.c
ファイルの507行目付近にあります。このファイルは、cmd/6a
アセンブラの字句解析器が使用する命令の定義テーブルを含んでいます。
追加された行は以下の通りです。
"MOVQL", LTYPE3, AMOVQL,
これは、アセンブラが MOVQL
という文字列を認識し、それを LTYPE3
型の AMOVQL
という内部命令コードにマッピングするように指示しています。この変更により、Goコンパイラが生成するアセンブリコードに MOVQL
が含まれていても、cmd/6a
アセンブラがエラーを発生させることなく、その命令を正しく解析できるようになります。
このテーブルは、アセンブラがソースコードをトークン化する際の辞書のような役割を果たします。新しい命令が追加されるたびに、このように lex.c
にその命令のニーモニックと対応する内部コードが登録されるのが一般的なパターンです。
関連リンク
- Go Code Review: https://golang.org/cl/54660046
参考にした情報源リンク
- Go Assembler: https://go.dev/doc/asm
- Go Assembler (Semi-Abstract Instruction Set): https://go.dev/blog/go1.5-compiler
- x86-64 MOV instruction: https://www.felixcloutier.com/x86/mov
- Lexical Analysis: https://www.geeksforgeeks.org/lexical-analysis-in-compiler-design/
- Rob Pike's Lexical Scanning in Go: https://github.com/yashi/lex (これはGoアセンブラの直接のソースではありませんが、字句解析の概念を理解するのに役立ちます)
- Go Assembler Syntax (Stack Overflow): https://stackoverflow.com/questions/17000000/go-assembler-syntax
- Go Tool Compile -S (Stack Overflow): https://stackoverflow.com/questions/22000000/go-tool-compile-s
- x86-64 Assembly Language Programming (MIT): https://ocw.mit.edu/courses/6-823-computer-system-architecture-fall-2012/resources/lecture-1-introduction-and-x86-64-assembly/
- x86-64 Assembly (HackMD): https://hackmd.io/@sysprog/x86-64-assembly
- x86-64 Assembly Language (Stanford): https://web.stanford.edu/class/cs107/lectures/10-x86-64-assembly.pdf
- Go Lexer Generators: https://go.dev/blog/lexical-scanning-in-go
- Go Lexer Generators (GitHub): https://github.com/golang/go/wiki/LexerGenerators