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

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

このコミットは、Go言語のmisc/cgo/test/backdoorディレクトリに、gccgoコンパイラ向けのbackdoor関数のバージョンを追加するものです。具体的には、Issue7695というGo関数がgcコンパイラではruntime.cで定義されているのに対し、gccgoでは適切なpkgpathを取得する方法がないため、このテストがgccgoにとって重要ではないという判断のもと、gccgo専用のスタブ実装を提供しています。

コミット

commit 9fc6c0598bc57099a792ffdd5c4e7bfc913f875d
Author: Ian Lance Taylor <iant@golang.org>
Date:   Sat Apr 26 22:31:32 2014 -0700

    misc/cgo/test/backdoor: add gccgo version of backdoor function
    
    For the gc compiler the Go function Issue7695 is defined in
    runtime.c, but there is no way to do that for gccgo, because
    there is no way to get the correct pkgpath.  The test is not
    important for gccgo in any case.
    
    LGTM=bradfitz
    R=golang-codereviews, bradfitz
    CC=golang-codereviews
    https://golang.org/cl/93870044

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

https://github.com/golang/go/commit/9fc6c0598bc57099a792ffdd5c4e7bfc913f875d

元コミット内容

misc/cgo/test/backdoor: add gccgo version of backdoor function

gcコンパイラでは、Go関数Issue7695runtime.cで定義されていますが、gccgoでは正しいpkgpathを取得する方法がないため、これは不可能です。いずれにせよ、このテストはgccgoにとって重要ではありません。

変更の背景

Go言語には、公式のコンパイラであるgc(Go Compiler)と、GCC(GNU Compiler Collection)をバックエンドとして利用するgccgoという2つの主要なコンパイラが存在します。これらはそれぞれ異なる実装を持ち、特にランタイムやCgo(GoとC言語の相互運用機能)の扱いにおいて差異があります。

このコミットの背景には、gcコンパイラ向けに書かれた特定のテストケース(Issue7695に関連するものと推測されます)が、gccgoのアーキテクチャと互換性がなかったという問題があります。具体的には、gcコンパイラではC言語のソースファイル(runtime.c)内でGo関数を定義し、それをGoコードから利用するような特殊なメカニズムが用いられていたようです。しかし、gccgoではこのような「C言語側からGo関数を定義し、Go側から参照する」というパターンにおいて、Goパッケージのパス(pkgpath)を正しく解決できないという制約がありました。

テストの目的は、特定の機能やバグの再現性を確認することにありますが、このIssue7695に関連するテストは、gccgoの機能性や安定性にとって本質的に重要ではないと判断されました。そのため、テストスイート全体がgccgoで実行される際に、この互換性のないテストがビルドエラーや実行時エラーを引き起こすのを避けるために、gccgo専用の代替実装(スタブ)を提供する必要が生じました。

前提知識の解説

  • Goコンパイラ (gc): Go言語の公式かつ主要なコンパイラです。Go言語で書かれたコードを直接機械語にコンパイルします。ランタイム(ガベージコレクション、スケジューラなど)もGo言語とC言語の組み合わせで実装されています。
  • gccgo: GCCのフロントエンドとしてGo言語をサポートするコンパイラです。GoコードをGCCの中間表現に変換し、GCCの最適化パスとバックエンドを利用して機械語を生成します。gcとは異なるランタイム実装やCgoのメカニズムを持つことがあります。
  • Cgo: Go言語とC言語のコードを相互に呼び出すためのメカニズムです。GoプログラムからC関数を呼び出したり、CプログラムからGo関数を呼び出したりすることができます。Cgoは、Goのビルドプロセスにおいて、GoとCのコードを適切にリンクするために重要な役割を果たします。
  • runtime.c: Go言語のランタイムの一部をC言語で実装しているファイルです。Goのガベージコレクタ、スケジューラ、メモリ管理などの低レベルな機能の一部がC言語で書かれており、Goコードからこれらの機能が利用されます。
  • pkgpath (パッケージパス): Go言語において、パッケージを一意に識別するためのパスです。例えば、"fmt""net/http"などがパッケージパスです。Cgoを通じてGo関数をC言語側から参照する場合など、コンパイラがGo関数の正しい定義を見つけるためには、このパッケージパスが正確に解決される必要があります。
  • ビルドタグ (+build): Goのソースファイルに記述される特殊なコメント行で、特定の条件(OS、アーキテクチャ、コンパイラなど)に基づいてファイルのコンパイルを制御します。例えば、+build gccgoは、そのファイルがgccgoコンパイラを使用する場合にのみビルドされることを意味します。これにより、コンパイラごとに異なる実装を提供することが可能になります。
  • スタブ関数: 実際の処理を行わず、最小限の機能(例えば、空の関数本体)を提供する関数です。主に、開発中の機能のプレースホルダーとして、または特定の環境で不要な機能を無効化するために使用されます。

技術的詳細

このコミットの技術的な核心は、gcコンパイラとgccgoコンパイラ間でのCgoの挙動、特にC言語側からGo関数を参照する際のpkgpath解決メカニズムの違いにあります。

gcコンパイラでは、runtime.cのようなC言語のファイル内でGo関数(この場合はIssue7695)を定義し、Goのランタイムと連携させることが可能です。これは、gcコンパイラがGoとCのコードを統合する独自のリンケージメカニズムを持っているためです。しかし、gccgoはGCCのフレームワークを利用するため、GoのパッケージシステムとGCCのシンボル解決が完全に一致しない場合があります。特に、C言語のコンテキストからGoの特定のパッケージに属する関数を参照しようとすると、gccgoがそのGo関数の正しいpkgpathを解決できず、ビルドエラーとなる可能性がありました。

コミットメッセージにある「there is no way to get the correct pkgpath」という記述は、このgccgoの制約を明確に示しています。Issue7695という関数が、gcコンパイラではruntime.cというC言語のファイル内で定義されているにもかかわらず、Goの関数として振る舞うという特殊なケースであったため、gccgoではそのGo関数がどのGoパッケージに属するのかを特定できず、結果としてリンクエラーが発生していたと考えられます。

この問題を解決するために、開発者はgccgoコンパイラを使用する場合にのみビルドされる新しいGoソースファイルbackdoor_gccgo.goを追加しました。このファイルには、Issue7695という名前の空の関数が定義されています。

// +build gccgo

package backdoor

func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) {}
  • // +build gccgo: このビルドタグにより、このファイルはgccgoコンパイラでビルドされる場合にのみコンパイルされます。gcコンパイラでビルドされる際には無視されます。
  • package backdoor: このファイルがbackdoorパッケージに属することを示します。
  • func Issue7695(...) {}: gcコンパイラでruntime.cに定義されていたIssue7695関数と同じシグネチャを持つ空の関数を定義しています。これにより、gccgoがこの関数を必要とする際に、シンボル解決の要件を満たすことができます。関数本体が空であることから、この関数が実際の処理を行うことを意図しておらず、単にリンケージエラーを回避するためのスタブであることがわかります。

このアプローチにより、gccgoIssue7695というシンボルを見つけることができるようになり、テストスイートのビルドが成功するようになります。同時に、このテストがgccgoにとって重要ではないという判断に基づき、実際の機能は実装せず、最小限の変更で互換性の問題を解決しています。

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

変更は、misc/cgo/test/backdoor/backdoor_gccgo.goという新しいファイルの追加です。

--- /dev/null
+++ b/misc/cgo/test/backdoor/backdoor_gccgo.go
@@ -0,0 +1,11 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is the gccgo version of the stub in runtime.c.
+
+// +build gccgo
+
+package backdoor
+
+func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) {}

コアとなるコードの解説

追加されたbackdoor_gccgo.goファイルは、以下の要素で構成されています。

  1. 著作権表示: Goプロジェクトの標準的な著作権ヘッダが含まれています。
  2. コメント: // This is the gccgo version of the stub in runtime.c. というコメントがあり、このファイルがruntime.c内のスタブのgccgo版であることを明示しています。これは、gcコンパイラとgccgoコンパイラで同じ論理的な機能(この場合はIssue7695関数)が異なる方法で実装されていることを示唆しています。
  3. ビルドタグ: // +build gccgo は、このファイルがgccgoコンパイラを使用する場合にのみビルドされることを保証します。これにより、gcコンパイラを使用するビルドではこのファイルが無視され、既存のruntime.c内の定義が使用されます。
  4. パッケージ宣言: package backdoor は、このファイルがbackdoorパッケージの一部であることを示します。これは、テストスイートの構造に合わせています。
  5. 関数定義: func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) {} は、Issue7695という名前のGo関数を定義しています。
    • この関数は8つのuintptr型の引数を取りますが、関数本体は空です。これは、この関数が実際の処理を行うことを意図しておらず、単にgccgoがこのシンボルを解決できるようにするためのプレースホルダー(スタブ)であることを明確に示しています。
    • uintptr型は、ポインタを保持できる整数型であり、GoのポインタとCのポインタの間で値をやり取りする際によく使用されます。引数の数と型は、おそらくgcコンパイラ側のruntime.cで定義されている元のIssue7695関数のシグネチャと一致させていると考えられます。

この変更により、gccgoでビルドする際にIssue7695関数が見つからないというリンケージエラーが解消され、テストスイートが正常に動作するようになります。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • GCCGoのドキュメント(GCCのウェブサイトなど)
  • Go言語のソースコード(特にruntimeパッケージとmisc/cgoディレクトリ)
  • コミットメッセージと差分情報