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

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

このコミットは、Go言語のビルドシステムにおいて、Plan 9オペレーティングシステム向けにintptr型の定義を追加するものです。具体的には、src/pkg/runtime/stack.hで導入されたStackPreempt定数の定義が、Plan 9環境でコンパイルエラーを引き起こす可能性があったため、その問題を解決するために行われました。intptrはポインタを保持できる整数型であり、異なるアーキテクチャ(386, amd64, arm)のPlan 9固有のヘッダファイルにこの定義が欠けていたことが原因でした。

コミット

  • コミットハッシュ: 636169405c370e3010f7a08162ed83b0da013b49
  • Author: Anthony Martin ality@pbrane.org
  • Date: Tue Jun 4 16:21:04 2013 -0700

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

https://github.com/golang/go/commit/636169405c370e3010f7a08162ed83b0da013b49

元コミット内容

    build: add intptr typedef for Plan 9
    
    Revision 01810e5c68e9 added the following to src/pkg/runtime/stack.h:
    
            StackPreempt = (uintptr)(intptr)0xffffade,
    
    The typedef for intptr is defined in two places:
    
            1. src/pkg/runtime/runtime.h for use by the runtime
    
            2. include/u.h for use by the compilers and linkers
    
    On Plan 9, we don't use include/u.h but instead augment the host's
    u.h with extra typedefs. These are in include/plan9/GOARCH/u.h.
    
    We forgot to add intptr. It didn't cause a problem until now since
    that typedef was never used outside the runtime.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/10023043

変更の背景

このコミットの背景には、Goランタイムのスタック管理に関連する変更があります。以前のコミット(リビジョン 01810e5c68e9)で、src/pkg/runtime/stack.hファイルにStackPreempt = (uintptr)(intptr)0xffffade,という行が追加されました。この行は、スタックのプリエンプション(横取り)に関連する定数を定義しており、intptr型へのキャストを含んでいます。

Goのビルドシステムでは、intptr型は通常、ランタイム内部で使用されるsrc/pkg/runtime/runtime.hと、コンパイラやリンカが使用するinclude/u.hの2箇所で定義されています。しかし、Plan 9オペレーティングシステムの場合、Goは標準のinclude/u.hを使用せず、代わりにホストのu.hを拡張する形で、include/plan9/GOARCH/u.hGOARCHはアーキテクチャ名、例: 386, amd64, arm)に独自の型定義を追加しています。

このPlan 9固有のu.hファイル群にintptrの型定義が欠けていたため、StackPreemptの定義が導入された際に、Plan 9環境でのビルドが失敗する問題が発生しました。これまではintptrがランタイム外部で直接使用されることがなかったため問題が顕在化しませんでしたが、今回の変更でその必要性が生じたため、このコミットで対応されました。

前提知識の解説

Plan 9

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソースをファイルとして表現し、それらをネットワークを通じて透過的にアクセスできるという特徴を持っています。Go言語の設計者の一部(Ken Thompson, Rob Pike, Russ Coxなど)はPlan 9の開発にも深く関わっており、Go言語の設計やツールチェインにはPlan 9の影響が色濃く見られます。例えば、Goのツールチェイン(コンパイラやアセンブラ)はPlan 9のツールチェインから派生しており、GoのABI(Application Binary Interface)もPlan 9のものを借用しています。

intptruintptr

intptruintptrは、ポインタの値を保持できる整数型です。

  • intptr: ポインタを保持できる符号付き整数型です。そのサイズは、実行環境のポインタのサイズ(通常は32ビットまたは64ビット)に依存します。C言語などでは、ポインタと整数型の間で相互変換を行う際に、ポインタのサイズに合わせた整数型として使用されることがあります。
  • uintptr: ポインタを保持できる符号なし整数型です。Go言語では、uintptrは任意のポインタのビットパターンを保持するのに十分な大きさを持つことが保証されています。Goのuintptrは、主に低レベルのメモリ操作や、unsafeパッケージと組み合わせてポインタ演算を行う際に使用されます。Goの型付きポインタ(*T)とは異なり、uintptrは型安全ではありません。また、Goのガベージコレクタはuintptrの値を追跡しないため、uintptrのみによって参照されているオブジェクトはガベージコレクションの対象となる可能性があります。

このコミットでは、intptrがGoのランタイムコード内で使用される際に、Plan 9環境でその型が未定義であったことが問題となりました。

Goのランタイムとコンパイラ

Go言語のランタイムは、ガベージコレクション、スケジューリング、メモリ管理など、Goプログラムの実行をサポートする低レベルのコードの集合体です。コンパイラはGoのソースコードを実行可能なバイナリに変換しますが、その過程でランタイムのコードとリンクされます。ランタイムとコンパイラは、特定の低レベルの型定義(例えば、ポインタのサイズに依存する整数型)を共有する必要があります。これらの型定義は、通常、ヘッダファイル(C言語の慣習に倣って)に記述され、異なるアーキテクチャやOS向けに調整されることがあります。

技術的詳細

このコミットの技術的な核心は、GoのビルドシステムがPlan 9環境でintptr型を正しく認識できるようにすることです。

Goのランタイムコード、特にsrc/pkg/runtime/stack.hで定義されたStackPreempt定数は、uintptr型とintptr型へのキャストを伴います。

StackPreempt = (uintptr)(intptr)0xffffade,

この行は、0xffffadeというリテラル値をまずintptrにキャストし、次にuintptrにキャストしています。これは、特定のメモリアドレスやオフセットを表現するために行われる一般的な手法です。

Goのビルドシステムでは、intptrの型定義は以下の2つの場所で提供されています。

  1. src/pkg/runtime/runtime.h: Goランタイム内部で使用される定義。
  2. include/u.h: コンパイラやリンカが使用する定義。

しかし、Plan 9オペレーティングシステムの場合、Goは標準のinclude/u.hを直接使用せず、代わりにPlan 9のホストシステムが提供するu.hを拡張する形で、Go固有の型定義をinclude/plan9/GOARCH/u.hGOARCH386, amd64, armなどのアーキテクチャ名)に配置しています。

このinclude/plan9/GOARCH/u.hファイル群にintptrの型定義が欠けていたため、StackPreemptの定義が導入された際に、Plan 9環境でコンパイルエラーが発生しました。具体的には、コンパイラがintptrという型を認識できず、「未定義の型」としてエラーを報告したと考えられます。

このコミットは、各アーキテクチャ(386, amd64, arm)に対応するinclude/plan9/GOARCH/u.hファイルに、それぞれのアーキテクチャに適したintptrの型定義を追加することで、この問題を解決しています。これにより、Plan 9環境でもStackPreempt定数が正しくコンパイルされるようになります。

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

このコミットでは、以下の3つのファイルが変更されています。

  1. include/plan9/386/u.h
  2. include/plan9/amd64/u.h
  3. include/plan9/arm/u.h

それぞれのファイルで、既存の型定義のリストにintptrの定義が追加されています。

include/plan9/386/u.h の変更点:

--- a/include/plan9/386/u.h
+++ b/include/plan9/386/u.h
@@ -4,11 +4,12 @@
 
 #include "/386/include/u.h"
 
-typedef char   int8;
-typedef uchar  uint8;
-typedef short  int16;
-typedef ushort uint16;
-typedef int    int32;
-typedef uint   uint32;
-typedef vlong  int64;
-typedef uvlong uint64;
+typedef	char	int8;
+typedef	uchar	uint8;
+typedef	short	int16;
+typedef	ushort	uint16;
+typedef	int	int32;
+typedef	uint	uint32;
+typedef	vlong	int64;
+typedef	uvlong	uint64;
+typedef	int	intptr; // この行が追加

include/plan9/amd64/u.h の変更点:

--- a/include/plan9/amd64/u.h
+++ b/include/plan9/amd64/u.h
@@ -4,11 +4,12 @@
 
 #include "/amd64/include/u.h"
 
-typedef char   int8;
-typedef uchar  uint8;
-typedef short  int16;
-typedef ushort uint16;
-typedef int    int32;
-typedef uint   uint32;
-typedef vlong  int64;
-typedef uvlong uint64;
+typedef	char	int8;
+typedef	uchar	uint8;
+typedef	short	int16;
+typedef	ushort	uint16;
+typedef	int	int32;
+typedef	uint	uint32;
+typedef	vlong	int64;
+typedef	uvlong	uint64;
+typedef	vlong	intptr; // この行が追加

include/plan9/arm/u.h の変更点:

--- a/include/plan9/arm/u.h
+++ b/include/plan9/arm/u.h
@@ -4,11 +4,12 @@
 
 #include "/arm/include/u.h"
 
-typedef char   int8;
-typedef uchar  uint8;
-typedef short  int16;
-typedef ushort uint16;
-typedef int    int32;
-typedef uint   uint32;
-typedef vlong  int64;
-typedef uvlong uint64;
+typedef	char	int8;
+typedef	uchar	uint8;
+typedef	short	int16;
+typedef	ushort	uint16;
+typedef	int	int32;
+typedef	uint	uint32;
+typedef	vlong	int64;
+typedef	uvlong	uint64;
+typedef	int	intptr; // この行が追加

コアとなるコードの解説

u.hファイルに追加されたtypedef行は、それぞれのアーキテクチャにおけるintptrの具体的なサイズを定義しています。

  • include/plan9/386/u.h および include/plan9/arm/u.h:

    typedef	int	intptr;
    

    これは、32ビットアーキテクチャである386(x86)とARMにおいて、intptrが標準のint型(通常32ビット)と同じサイズであることを示しています。これは、これらのアーキテクチャにおけるポインタのサイズが32ビットであることに対応しています。

  • include/plan9/amd64/u.h:

    typedef	vlong	intptr;
    

    これは、64ビットアーキテクチャであるamd64(x86-64)において、intptrvlong型と同じサイズであることを示しています。Plan 9のコンテキストでは、vlongは通常64ビット整数を意味します。これは、amd64アーキテクチャにおけるポインタのサイズが64ビットであることに対応しています。

これらの変更により、GoのビルドプロセスがPlan 9環境でStackPreempt定数をコンパイルする際に、intptr型が正しく解決されるようになり、ビルドエラーが解消されます。これは、Goが異なるプラットフォームやアーキテクチャで一貫して動作するための、低レベルな互換性維持の典型的な例と言えます。

関連リンク

参考にした情報源リンク