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

[インデックス 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 命令を clearload 命令に最適化するなど)を行うことができます。

したがって、このコミットの背景には、Goコンパイラまたはランタイムの内部的なコード生成ロジックが MOVQL という概念を使用しており、それをアセンブラが正しく字句解析できるようにする必要があったという事情が考えられます。これは、特定の最適化パスや、特定のデータ型(例えば、long longquadword に対応するGoの型)の処理に関連している可能性があります。

前提知識の解説

Goアセンブラ (cmd/6a)

Go言語は高水準言語ですが、ランタイムのブートストラップ、スタック管理、コンテキストスイッチなどの低レベルな操作、あるいはパフォーマンスが重要な特定のライブラリ(例: math/big)ではアセンブリコードが使用されます。

  • 歴史的背景: Go言語の初期のバージョンでは、Plan 9オペレーティングシステム由来のアセンブラが使用されていました。6a はAMD64 (x86-64) アーキテクチャ用、8a は386アーキテクチャ用でした。これらはC言語で書かれた独立したプログラムでした。
  • 半抽象的な命令セット: Goアセンブラの重要な特徴は、それが直接的な機械語命令を表現するのではなく、半抽象的な命令セットで動作する点です。例えば、MOV 命令は常に直接的な機械語の MOV 命令に対応するわけではなく、ツールチェーンによって clearload 命令に最適化されることがあります。命令選択はコード生成の後に行われる部分もあります。
  • 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 にその命令のニーモニックと対応する内部コードが登録されるのが一般的なパターンです。

関連リンク

参考にした情報源リンク