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

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

このコミットは、Go言語のアセンブラである 6a (amd64アーキテクチャ用) と 8a (armアーキテクチャ用) において、浮動小数点定数の負の値を表現する際の構文の柔軟性を向上させるものです。具体的には、$-1 のような形式に加えて、$(-1) のような括弧で囲まれた負の浮動小数点定数も許容するようにパーサーの文法が拡張されました。これにより、既存の $1$(1) といった他の即値表現との一貫性が保たれます。

コミット

commit 6d9c02aea3e902633ca62b220686580705bdcaf8
Author: Russ Cox <rsc@golang.org>
Date:   Fri Nov 11 14:56:49 2011 -0500

    6a, 8a: allow $(-1) for consistency with $1, $(1), $-1.
    
    R=ken2
    CC=golang-dev
    https://golang.org/cl/5373074

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

https://github.com/golang/go/commit/6d9c02aea3e902633ca62b220686580705bdcaf8

元コミット内容

Go言語のアセンブラである 6a および 8a において、即値(immediate value)として負の浮動小数点定数を指定する際に、$(-1) のような括弧で囲む形式を許可する変更です。これは、既にサポートされている $1 (正の整数)、$(1) (括弧で囲まれた正の整数)、$-1 (負の浮動小数点数) との構文上の一貫性を確保することを目的としています。

変更の背景

Go言語のアセンブラは、Plan 9オペレーティングシステムのアセンブラに由来する独自の構文を使用しています。この構文では、即値は通常 $ 記号で始まります。例えば、$1 は数値 1 を即値として指定します。

これまでのアセンブラでは、負の浮動小数点定数を即値として指定する場合、$-1.0 のように $ の直後に負符号を置く形式がサポートされていました。しかし、正の整数値では $(1) のように括弧で囲む形式も許容されており、これはより複雑な式を即値として評価する際に利用されることがあります。

このコミットの背景には、負の浮動小数点定数についても、他の即値表現と同様に括弧で囲む形式 ($(-1.0)) をサポートすることで、アセンブラの構文全体の一貫性を高め、開発者がより直感的にコードを記述できるようにするという意図があります。これにより、パーサーがより多様な有効な構文を認識できるようになり、将来的な拡張性や、より複雑な即値表現への対応が容易になります。

前提知識の解説

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

  1. Go言語のアセンブラ (Plan 9 Assembler Syntax): Go言語は、独自の「Plan 9アセンブラ」構文を使用しています。これは一般的なAT&T構文やIntel構文とは異なります。主な特徴として、レジスタ名、命令のニーモニック、オペランドの記述方法などが挙げられます。即値は $ 記号でプレフィックスされます。例えば、MOVQ $1, AX は即値 1AX レジスタに移動する命令です。

  2. Yacc/Bison (パーサー生成器): a.y ファイルは、Yacc (Yet Another Compiler Compiler) またはそのGNU版であるBisonによって処理される文法定義ファイルです。Yacc/Bisonは、指定された文法規則に基づいて、入力ストリーム(この場合はアセンブリコード)を解析するためのC言語のパーサーコードを生成します。

    • .y ファイルには、字句解析器(lexer)からのトークンと、それらのトークンがどのように組み合わされて文法構造(プロダクションルール)を形成するかを定義します。
    • 各プロダクションルールには、そのルールがマッチしたときに実行されるC言語のコード(アクション)を記述できます。このアクションは、抽象構文木(AST)の構築や、セマンティックな処理を行うために使用されます。
    • $$ は現在のプロダクションのセマンティック値(通常はASTノードなど)を表し、$1, $2, ... はプロダクションの右辺の各シンボルのセマンティック値を表します。
  3. 即値 (Immediate Value): アセンブリ言語において、即値とは命令の一部として直接エンコードされる定数のことです。例えば、ADD AX, 5 という命令では、5 が即値です。これはレジスタやメモリから値をロードするのではなく、命令自体に値が含まれているため、高速な処理が可能です。

  4. 浮動小数点定数 (Floating-Point Constant): 小数点を含む数値(例: 3.14, -0.5)のことです。アセンブリ言語では、これらの定数は特定の形式で表現され、浮動小数点演算ユニット(FPU)によって処理されます。

技術的詳細

このコミットは、Goアセンブラのフロントエンド、特に字句解析と構文解析の層に影響を与えます。変更が加えられた src/cmd/6a/a.ysrc/cmd/8a/a.y は、それぞれamd64とarmアーキテクチャ用のアセンブラのYacc文法定義ファイルです。

既存の文法では、imm (immediate value) のプロダクションルールに、'$' '-' LFCONST という形式が含まれていました。これは、$-1.0 のように $ の直後に負符号と浮動小数点定数 LFCONST が続くパターンを認識します。このルールがマッチすると、LFCONST の値に負符号を適用し、その結果を即値として扱います。

今回の変更では、この imm プロダクションに新しいルールが追加されました。 '$' '(' '-' LFCONST ')'

この新しいルールは、$、開く括弧 (、負符号 -、浮動小数点定数 LFCONST、閉じる括弧 ) の順序でトークンが並んだパターンを認識します。このパターンがマッチした場合も、既存の $-LFCONST の場合と同様に、LFCONST の値に負符号を適用し、その結果を即値として扱います。

Yaccの文法定義において、LFCONST はおそらく字句解析器によって識別される浮動小数点定数のトークンです。$4 は、この新しいプロダクションルール '$' '(' '-' LFCONST ')' において、4番目のシンボルである LFCONST のセマンティック値を参照しています。したがって、$$.dval = -$4; は、LFCONST の値に負符号を適用した結果を、即値のセマンティック値 $$dval (double value) フィールドに格納することを意味します。

この変更により、アセンブラは $-1.0$-(1.0) の両方を有効な即値として解釈できるようになり、アセンブリコードの記述においてより柔軟な表現が可能になります。これは、パーサーの堅牢性を高め、将来的な文法拡張の基盤を築く上でも重要です。

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

変更は src/cmd/6a/a.ysrc/cmd/8a/a.y の両ファイルに、全く同じ内容で適用されています。

--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -429,6 +429,12 @@ imm:
 		$$.type = D_FCONST;
 		$$.dval = $3;
 	}
+|\t'$' '(' '-' LFCONST ')'
+\t{
+\t\t$$ = nullgen;
+\t\t$$.type = D_FCONST;
+\t\t$$.dval = -$4;
+\t}
 |\t'$' '-' LFCONST
 	{
 		$$ = nullgen;

コアとなるコードの解説

上記のコードスニペットは、Yacc文法定義ファイルにおける imm (immediate value) プロダクションの一部です。

  • imm:: これは、即値の構文規則を定義するプロダクションの開始を示します。
  • |\t'$' '(' '-' LFCONST ')':
    • | は、前のルールに加えて、この新しいルールも imm プロダクションの一部であることを示します。
    • '$', '(', '-', ')' は、それぞれリテラルトークン(アセンブリコードに直接現れる文字)です。
    • LFCONST は、字句解析器によって識別される浮動小数点定数を表すトークンです。
    • この行全体で、$(-、浮動小数点定数、) の順序で並んだ文字列が即値として認識されるべき新しい構文パターンを定義しています。例えば、$(-1.23) のような形式です。
  • { ... }: この波括弧内は、この文法ルールがマッチしたときに実行されるC言語のアクションコードです。
    • $$ = nullgen;: nullgen は、おそらくアセンブラの内部表現で、新しい即値オブジェクトを生成または初期化するためのヘルパー関数やマクロです。$$ は、この imm プロダクション全体のセマンティック値を表します。
    • $$.type = D_FCONST;: 生成された即値オブジェクトの型を D_FCONST (浮動小数点定数) に設定します。
    • $$.dval = -$4;: ここが変更の核心です。$4 は、このプロダクションルール '$' '(' '-' LFCONST ')' における4番目のシンボル、すなわち LFCONST のセマンティック値(実際の浮動小数点数値)を参照します。この値に負符号を適用 (- 演算子) し、その結果を即値オブジェクトの dval (double value) フィールドに格納します。これにより、例えば $(-1.23)-1.23 という浮動小数点値として正しく解釈されます。

この変更により、アセンブラのパーサーは、$-1.0$-(1.0) の両方を同じ意味で解釈できるようになり、アセンブリコードの記述における柔軟性と一貫性が向上します。

関連リンク

  • Go言語の公式ドキュメント (アセンブリ): Go言語のアセンブリに関する公式ドキュメントは、Goのツールチェーンとアセンブリ言語の構文について詳しく説明しています。
  • Go言語のソースコードリポジトリ: このコミットが含まれるGo言語の公式リポジトリです。
  • Go CL (Change List) 5373074: このコミットに対応するGoのコードレビューシステム(Gerrit)上の変更リストです。より詳細な議論やレビューコメントが含まれている可能性があります。

参考にした情報源リンク

  • Yacc/Bison ドキュメンテーション: YaccやBisonの文法定義とアクションに関する一般的な情報源。
  • Plan 9 Assembler: GoアセンブラのルーツであるPlan 9アセンブラに関する情報。
  • Go言語のコンパイラとツールチェーンに関する記事や書籍: Goの内部構造やコンパイラの動作について解説している資料。
    • 特定の書籍や記事は挙げませんが、Goのコンパイラやアセンブラの仕組みを理解するための一般的な情報源を参照しました。