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

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

このコミットは、Go言語のコンパイラ(cmd/go)とランタイム(src/pkg/runtime/cgo/gcc_arm.S)におけるARMv5tアーキテクチャの指定方法の変更に関するものです。具体的には、GCCのコマンドラインに-march=armv5tフラグを追加する代わりに、アセンブリファイル内で.arch armv5tという擬似命令を使用するように変更されました。これにより、ARMv5t命令を使用するアセンブリコードが、より適切にコンパイルされるようになります。

コミット

commit 254dc5fdbee675ca7c85f7b76247313b7b356dee
Author: Carl Shapiro <cshapiro@google.com>
Date:   Tue Oct 8 10:40:51 2013 -0700

    cmd/go, runtime: express armv5t architecture constraint differently
    
    Instead of adding an -march=armv5t flag to the gcc command
    line, the same effect is obtained with an ".arch armv5t"
    pseudo op in the assembly file that uses armv5t instructions.
    
    R=golang-dev, iant, dave
    CC=golang-dev
    https://golang.org/cl/14511044

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

https://github.com/golang/go/commit/254dc5fdbee675ca7c85f7b76247313b7b356dee

元コミット内容

cmd/go, runtime: express armv5t architecture constraint differently

このコミットは、GoコンパイラとランタイムがARMv5tアーキテクチャの制約を表現する方法を変更します。具体的には、GCCコマンドラインに-march=armv5tフラグを追加する代わりに、ARMv5t命令を使用するアセンブリファイル内で.arch armv5tという擬似命令を使用することで、同じ効果が得られるようにします。

変更の背景

Go言語は、ARMv5を含む様々なARMアーキテクチャをサポートしています。ARMv5tは、ARMv5アーキテクチャにThumb命令セットのサポートを追加したものです。GoのランタイムやCgo(GoとC言語の相互運用機能)のコードには、特定のARM命令セットに依存するアセンブリコードが含まれることがあります。

以前は、GoコンパイラがCgoのコードをコンパイルする際に、GCCに対して-march=armv5tというフラグを渡していました。このフラグは、GCCにARMv5tアーキテクチャ向けのコードを生成するように指示するものです。しかし、アセンブラによっては、デフォルトで古いISA(Instruction Set Architecture)リビジョンをターゲットとする場合があり、その結果、ARMv5tで導入されたBLXのような特定の命令が正しく認識されない可能性がありました。

この問題に対処するため、コミットの著者は、アーキテクチャの指定方法を変更することを決定しました。コマンドラインフラグではなく、アセンブリファイル自体に.arch armv5tという擬似命令を埋め込むことで、アセンブラがそのファイル内の命令を解釈する際に、明示的にARMv5tのISAリビジョンを考慮するように強制できます。これにより、BLXのような重要な命令が常に正しく認識され、コンパイルエラーや予期せぬ動作を防ぐことができます。

前提知識の解説

ARMアーキテクチャとISA (Instruction Set Architecture)

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。ARMアーキテクチャには、ARMv4、ARMv5、ARMv6、ARMv7、ARMv8など、多くのバージョン(リビジョン)が存在し、それぞれ異なる命令セットや機能拡張を持っています。ISAは、CPUが理解し実行できる命令のセットを定義します。

ARMv5t

ARMv5tは、ARMv5アーキテクチャの拡張版です。特に重要なのは、Thumb命令セットのサポートが追加されたことです。Thumbは、16ビットの固定長命令で構成される命令セットで、コード密度を高め、メモリ使用量を削減するのに役立ちます。

BLX命令

BLX(Branch with Link and Exchange)命令は、ARMv5T命令セットの一部として導入されました。この命令は、サブルーチン呼び出しに使用され、ARM命令セットとThumb命令セットの間で切り替える機能を持っています。これは、異なる命令セットで書かれたコード間を効率的にジャンプするために非常に重要です。

GCCの-marchフラグ

GCC(GNU Compiler Collection)は、C、C++、Goなど、多くのプログラミング言語をコンパイルできるコンパイラです。-march=<architecture>フラグは、GCCに特定のCPUアーキテクチャ向けのコードを生成するように指示します。例えば、-march=armv5tは、ARMv5tアーキテクチャに最適化されたコードを生成するようにコンパイラに伝えます。

アセンブラの擬似命令 (.arch)

アセンブラは、アセンブリ言語のコードを機械語に変換するプログラムです。アセンブラは、実際のCPU命令だけでなく、「擬似命令(pseudo-op)」と呼ばれる特別なディレクティブもサポートしています。擬似命令は、アセンブラの動作を制御したり、データやセクションを定義したりするために使用されます。

.arch <architecture>は、アセンブラに対する擬似命令の一つで、ターゲットとするCPUアーキテクチャを明示的に指定します。これにより、アセンブラはそのアーキテクチャの命令セットに基づいてアセンブリコードを解釈し、適切な機械語を生成します。これは、特に古いアセンブラがデフォルトで最新の命令セットを認識しない場合に重要です。

GoのビルドシステムとCgo

Go言語は、独自のコンパイラ(gc)を持っていますが、C言語のコードと連携するCgo機能を使用する場合、GoのビルドシステムはGCCのような外部のCコンパイラを呼び出すことがあります。このコミットは、Cgoが関与するARMv5t向けのアセンブリコードのコンパイルプロセスに影響を与えます。

技術的詳細

この変更の核心は、ARMv5tアーキテクチャの制約をコンパイラコマンドライン(gcc -march=armv5t)からアセンブリソースコード自体(.arch armv5t)に移した点にあります。

  1. コマンドラインフラグの限界: GCCの-marchフラグは、コンパイラ全体に特定のアーキテクチャをターゲットとするよう指示しますが、アセンブラがデフォルトで古いISAリビジョンを想定している場合、アセンブラが特定の命令(例: BLX)を認識できない問題が発生する可能性があります。これは、コンパイラが生成するアセンブリコードが、アセンブラのデフォルト設定と矛盾する場合に起こりえます。

  2. .arch擬似命令の利点: アセンブリファイル内に.arch armv5tを直接記述することで、そのアセンブリファイルを処理するアセンブラに対して、明示的にARMv5tのISAリビジョンをターゲットとするよう指示できます。これにより、アセンブラはBLXのようなARMv5t固有の命令を正しく解釈し、エラーなくアセンブルできるようになります。これは、特にクロスコンパイル環境や、異なるバージョンのツールチェーンが混在する環境において、ビルドの堅牢性を高める効果があります。

  3. BLX命令の重要性: BLX命令は、ARMとThumb命令セット間の切り替えを可能にするため、GoのランタイムがCgoを介してCコードと連携する際に、異なるコンパイルモードで書かれたコード間を効率的に呼び出すために不可欠です。この命令が正しく認識されないと、ランタイムの動作に深刻な問題が生じる可能性があります。

この変更は、GoのビルドプロセスにおけるARMv5tサポートの信頼性と正確性を向上させるためのものであり、特にアセンブリレベルでの低レベルな最適化と互換性の確保に寄与します。

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

--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1903,7 +1903,7 @@ func (b *builder) gccArchArgs() []string {
 	case "6":
 		return []string{"-m64"}
 	case "5":
-		return []string{"-marm", "-march=armv5t"} // not thumb
+		return []string{"-marm"} // not thumb
 	}\n
 	return nil
 }
--- a/src/pkg/runtime/cgo/gcc_arm.S
+++ b/src/pkg/runtime/cgo/gcc_arm.S
@@ -11,6 +11,13 @@
 #define EXT(s) s
 #endif
 
+/*
+ * Because the assembler might target an earlier revision of the ISA
+ * by default, we must explicitly specify the ISA revision to ensure
+ * BLX is recognized as a valid instruction.
+ */	
+.arch armv5t
+
 /*
  * void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void *m, void *g), void *m, void *g)
  *\n

コアとなるコードの解説

src/cmd/go/build.go の変更

src/cmd/go/build.go ファイルは、Goのビルドコマンド(go buildなど)のロジックを定義しています。このファイル内のgccArchArgs()関数は、特定のアーキテクチャ向けにGCCを呼び出す際に渡す引数を決定します。

変更前:

case "5":
	return []string{"-marm", "-march=armv5t"} // not thumb

GOARM=5の場合(ARMv5tをターゲットとする場合)、GCCに-marm(ARM命令セットを使用)と-march=armv5t(ARMv5tアーキテクチャをターゲット)の両方のフラグを渡していました。

変更後:

case "5":
	return []string{"-marm"} // not thumb

変更後は、-march=armv5tフラグが削除され、-marmのみが残されました。これは、アーキテクチャの指定がGCCのコマンドラインからアセンブリファイル自体に移されたためです。

src/pkg/runtime/cgo/gcc_arm.S の変更

src/pkg/runtime/cgo/gcc_arm.S は、ARMアーキテクチャ向けのCgoランタイムの一部であるアセンブリファイルです。

追加されたコード:

/*
 * Because the assembler might target an earlier revision of the ISA
 * by default, we must explicitly specify the ISA revision to ensure
 * BLX is recognized as a valid instruction.
 */	
.arch armv5t

この変更により、アセンブリファイルの冒頭に新しいコメントブロックと.arch armv5tという擬似命令が追加されました。

  • コメント: アセンブラがデフォルトで古いISAリビジョンをターゲットにする可能性があるため、BLXが有効な命令として認識されるように、ISAリビジョンを明示的に指定する必要があることを説明しています。
  • .arch armv5t: この擬似命令は、このアセンブリファイルを処理するアセンブラに対して、ARMv5tアーキテクチャの命令セットをターゲットとするように指示します。これにより、BLXのようなARMv5t固有の命令が正しく解釈され、アセンブルされることが保証されます。

この二つの変更は連携しており、GoのビルドシステムがGCCに-march=armv5tを渡すのをやめ、その代わりにアセンブリファイル自体がアセンブラにアーキテクチャ情報を直接伝えるようにすることで、より堅牢で信頼性の高いビルドプロセスを実現しています。

関連リンク

参考にした情報源リンク