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

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

このコミットは、Go言語のランタイムにおいて、GoとC言語の混在コードを扱うための新しいツール cgo2c を導入するものです。これにより、Goの内部Cコンパイラである6cと、一般的なCコンパイラであるgccの間で存在した、関数の戻り値の扱いの非互換性を単一のソースファイルで吸収できるようになります。具体的には、.cgoという拡張子を持つファイルをC言語のソースファイルに変換する役割を担います。

コミット

commit 2b57a1124e87b0dc8bc1ff6899297b4d7d6e74f2
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Jan 14 08:21:25 2009 -0800

    Add cgo2c program to translate mixed Go/C code into C.  This
    lets us use a single source file for both 6c and gcc, handling
    the incompatible handling of return values.
    
    R=rsc
    DELTA=649  (613 added, 35 deleted, 1 changed)
    OCL=22682
    CL=22730

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

https://github.com/golang/go/commit/2b57a1124e87b0dc8bc1ff6899297b4d7d6e74f2

元コミット内容

Add cgo2c program to translate mixed Go/C code into C.  This
lets us use a single source file for both 6c and gcc, handling
the incompatible handling of return values.

変更の背景

Go言語の初期開発段階において、Goのランタイムや標準ライブラリの一部はC言語で記述されており、GoコードとCコードが混在する状況がありました。当時、Goには独自のCコンパイラである6c(64ビットアーキテクチャ向け)が存在し、これと一般的なgccコンパイラの両方でコードをコンパイルする必要がありました。

しかし、6cgccの間には、特に複数戻り値を持つ関数の呼び出し規約に関して非互換性がありました。Go言語の関数は複数の戻り値を返すことができますが、C言語の関数は通常単一の戻り値しか持ちません。GoのCgoメカニズムは、このGoの複数戻り値をC側でどのように表現し、受け渡すかについて、コンパイラ間で異なるアプローチを取っていました。

この非互換性のため、開発者は6cgccの両方でコンパイル可能なように、同じロジックを異なる方法で記述するか、条件付きコンパイル(#ifdefなど)を多用する必要がありました。これはコードの重複、保守性の低下、そして開発の複雑化を招いていました。

このコミットの目的は、この問題を解決し、GoとCの混在コードを単一のソースファイルで記述できるようにすることです。cgo2cというツールを導入することで、Goの関数シグネチャとCコードが混在する.cgoファイルを、6cgccのどちらでもコンパイル可能な標準的なCコードに変換し、コンパイラ間の戻り値の扱いの違いを吸収します。これにより、GoランタイムのC部分のコードベースを簡素化し、保守性を向上させることが可能になりました。

前提知識の解説

Go言語のCgo

Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGo言語の機能です。Goのソースファイル内にimport "C"という特殊なインポート文を記述し、その後にC言語のコードを直接埋め込むことで、GoとCの相互運用を可能にします。Cgoは、GoとCの異なる型システムやメモリ管理、関数呼び出し規約の間の橋渡しを行います。

6c (Goの内部Cコンパイラ)

6cは、Go言語の初期のツールチェーンに含まれていたCコンパイラの一つです。Goプロジェクトは、独自のコンパイラ群(6g for Go, 6c for C, 6a for assemblerなど)を持っていました。これらはGo言語の特定のニーズに合わせて設計されており、クロスコンパイルの容易さや、Goランタイムとの密接な連携を可能にしていました。しかし、6cは標準的なCコンコンパイラ(GCCなど)とは異なる挙動や最適化を行うことがあり、特にABI(Application Binary Interface)の面で非互換性が生じることがありました。

GCC (GNU Compiler Collection)

GCCは、C、C++、Objective-C、Fortran、Ada、Goなどの多くのプログラミング言語をサポートする、広く使われているコンパイラコレクションです。Go言語のプロジェクトでは、特定のプラットフォームや環境で6cが利用できない場合や、既存のCライブラリとの連携のためにgccを使用する必要がありました。

GoとCの関数呼び出し規約の違い(特に複数戻り値)

Go言語の大きな特徴の一つは、関数が複数の値を戻り値として返せることです。例えば、func foo() (int, error)のように記述できます。しかし、C言語の関数は通常、単一の戻り値しか持ちません。CgoがGoの複数戻り値をC側で扱う場合、いくつかの方法が考えられます。

  • 構造体による戻り値: 複数の戻り値をCの構造体としてまとめ、その構造体を返す。
  • ポインタ引数による戻り値: 戻り値を格納するためのポインタを引数として渡し、関数内でそのポインタが指すメモリに値を書き込む。

6cgccは、これらのアプローチにおいて異なるABIを採用していたため、同じGoの関数シグネチャから生成されるCの関数定義が異なり、直接的な相互運用が困難でした。

.cgoファイルとプリプロセッサ/トランスレータ

このコミットで導入される.cgoファイルは、Goの関数シグネチャとC言語のコードブロックを組み合わせた特殊な形式のソースファイルです。cgo2cは、この.cgoファイルを読み込み、Goの関数シグネチャをC言語の関数プロトタイプと定義に変換し、埋め込まれたCコードをそのまま出力するプリプロセッサ(またはトランスレータ)として機能します。これにより、Goの複数戻り値の概念をCの構造体やポインタ引数にマッピングする処理をcgo2cが担当し、最終的に生成されるCファイルは6cgccのどちらでも正しくコンパイルできるようになります。

技術的詳細

cgo2cプログラムは、標準入力から.cgoファイルを読み込み、標準出力にC言語のソースコードを出力するシンプルなコマンドラインツールです。その主な機能は以下の通りです。

  1. Goパッケージ名の読み込み: .cgoファイルの先頭にあるpackage PACKAGENAMEを読み込み、C言語の関数名にGoのパッケージ名をプレフィックスとして付与するために使用します(例: package·functionName)。
  2. プリプロセッサディレクティブのコピー: # lineのようなプリプロセッサディレクティブをそのまま出力します。
  3. Go関数シグネチャの解析:
    • func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] { の形式で記述されたGoの関数定義を解析します。
    • 関数名、引数リスト、戻り値リストを抽出します。
    • Goの型(例: *byte)をCの型(例: byte *)に変換します。
  4. C言語関数定義の生成:
    • 6c向け: void\npackage·name(param1 type1, param2 type2, ...) の形式で関数を定義します。Goの複数戻り値は、Cの引数リストの末尾にポインタとして追加されます。関数本体のCコードの後に、戻り値のポインタをフラッシュするFLUSHマクロが挿入されます。
    • gcc向け: Goの複数戻り値がある場合、それらを格納するためのCのstruct型を定義します(例: struct package_name_ret { type1 name1; type2 name2; };)。関数は、この構造体を戻り値として返すように定義されます。Goの関数名とCの関数名をasmキーワードでマッピングします(例: void package_name() asm ("package.name");)。
  5. Cコードブロックのコピー: Go関数シグネチャの後に続くCコードブロック({...}で囲まれた部分)を、ネストされたブレース、コメント、文字列リテラルを正しく処理しながら、そのまま出力します。これにより、Goの関数内でCのロジックを自由に記述できます。
  6. コマンドライン引数によるコンパイラ選択: cgo2c--6gまたは--gccというコマンドライン引数を受け取り、どちらのコンパイラ向けのCコードを生成するかを切り替えます。これにより、ビルドシステムが適切なコンパイラに合わせてcgo2cの出力を調整できます。

このメカニズムにより、Goのランタイムコードは、Goの複数戻り値のセマンティクスを維持しつつ、6cgccの両方でコンパイル可能な単一のCソースファイルとして記述できるようになりました。

src/runtime/Makefileの変更は、このcgo2cツールのビルドと利用をビルドプロセスに組み込むものです。

  • cgo2c: cgo2c.c ルールが追加され、cgo2c.cからcgo2c実行ファイルをビルドします。
  • %.c: %.cgo cgo2c ルールが追加され、.cgoファイルがcgo2cによって対応する.cファイルに変換されるようにします。
  • cleanターゲットにcgo2cの削除が追加されます。

src/runtime/malloc.cからGo関数スタブが削除され、それらがsrc/runtime/malloc_go.cgoに移行されたのは、malloc関連のGoとCの混在コードをcgo2cの管理下に置くためです。これにより、mallocのGoインターフェースが、cgo2cによって生成されるCコードを介して、6cgccの両方で一貫して動作するようになります。

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

このコミットの主要な変更は以下のファイルに集中しています。

  • src/runtime/cgo2c.c (新規追加): cgo2cプログラムのC言語ソースコード。GoとCの混在コードをCコードに変換するロジックが実装されています。
  • src/runtime/Makefile (変更): cgo2cのビルドと、.cgoファイルを.cファイルに変換するルールが追加されました。
  • src/runtime/malloc.c (変更): malloc_Alloc, malloc_Free, malloc_Lookup, malloc_GetStatsといったGo関数スタブが削除されました。これらの機能はcgo2cを介して提供されるようになります。
  • src/runtime/malloc.h (変更): malloc, free, mlookupの関数プロトタイプが追加されました。
  • src/runtime/malloc_go.cgo (新規追加): malloc関連のGo関数とCコードを混在させた新しいソースファイル。cgo2cによって処理されます。

コアとなるコードの解説

src/runtime/cgo2c.c

このファイルは、Goの関数シグネチャとCコードを解析し、ターゲットコンパイラ(6cまたはgcc)に応じたCコードを生成する主要なロジックを含んでいます。

  • main関数:
    • コマンドライン引数--6gまたは--gccを解析し、flag_gccを設定します。
    • process_file関数を呼び出し、ファイル全体の処理を開始します。
  • process_file関数:
    • read_package()でGoのパッケージ名を読み込みます。
    • read_preprocessor_lines()でプリプロセッサディレクティブをコピーします。
    • ループ内でread_func_header()を呼び出し、Goの関数定義を一つずつ解析します。
    • 解析した関数情報(名前、引数、戻り値)に基づいて、write_func_header()でCの関数ヘッダを生成します。
    • copy_body()でGo関数内のCコードブロックをコピーします。
    • write_func_trailer()でCの関数トレーラ(戻り値の処理など)を生成します。
    • 解析したメモリを解放します。
  • read_token / read_token_no_eof:
    • 入力ストリームからトークン(識別子、区切り文字など)を読み込みます。
    • コメント(///* */)をスキップするロジックが含まれています。
  • read_type:
    • Goの型表現(例: *byte)をCの型表現(例: byte *)に変換します。ポインタの数を正しく処理します。
  • read_params:
    • Goの関数引数または戻り値のリストを解析し、名前と型のペアのリンクリストとして返します。
  • read_func_header:
    • funcキーワードから始まり、関数名、引数リスト、戻り値リスト、そして{までのGo関数シグネチャを解析します。
  • write_6g_func_header / write_6g_func_trailer:
    • 6cコンパイラ向けのC関数ヘッダとトレーラを生成します。Goの複数戻り値は、Cの引数として渡されるポインタとして扱われ、トレーラでFLUSHマクロが呼び出されます。
  • define_gcc_return_type / write_gcc_return_type / write_gcc_func_header / write_gcc_func_trailer:
    • gccコンパイラ向けのC関数ヘッダとトレーラを生成します。
    • Goの複数戻り値がある場合、それらをカプセル化するためのCのstruct型を定義し、関数はその構造体を戻り値として返します。
    • asmキーワードを使用して、Goの関数名とCの関数名をマッピングします。
  • copy_body:
    • Go関数定義内のCコードブロックを、ブレースのネストレベルを考慮しながら、そのまま出力します。文字列リテラルやコメント内のブレースを誤って解釈しないように注意深く処理されます。

src/runtime/malloc_go.cgo

このファイルは、cgo2cによって処理されるGoとCの混在コードの具体例です。

package malloc
#include "runtime.h"
#include "malloc.h"

func Alloc(n uintptr) (p *byte) {
	p = malloc(n);
}

func Free(p *byte) {
	free(p);
}

func Lookup(p *byte) (base *byte, size uintptr) {
	mlookup(p, &base, &size);
}

func GetStats() (s *MStats) {
	s = &mstats;
}

このファイルでは、mallocパッケージのGo関数Alloc, Free, Lookup, GetStatsが定義されています。それぞれのGo関数の中身はC言語のコードで記述されており、malloc, free, mlookupといったCの関数を呼び出しています。特にLookup関数はbasesizeという2つの戻り値を持っており、cgo2cがこれを6cgccの両方で正しく扱えるCコードに変換する役割を担います。

関連リンク

特になし。

参考にした情報源リンク

  • Go言語のCgoに関する公式ドキュメントやブログ記事 (当時の情報を見つけるのは困難なため、一般的なCgoの概念に限定)
  • Go言語の初期のコンパイラに関する議論やドキュメント (同上)
  • GCCのABIに関する一般的な情報
  • cgo2c.cのソースコード自体の詳細な分析

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

このコミットは、Go言語のランタイムにおいて、GoとC言語の混在コードを扱うための新しいツール cgo2c を導入するものです。これにより、Goの内部Cコンパイラである6cと、一般的なCコンパイラであるgccの間で存在した、関数の戻り値の扱いの非互換性を単一のソースファイルで吸収できるようになります。具体的には、.cgoという拡張子を持つファイルをC言語のソースファイルに変換する役割を担います。

コミット

commit 2b57a1124e87b0dc8bc1ff6899297b4d7d6e74f2
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Jan 14 08:21:25 2009 -0800

    Add cgo2c program to translate mixed Go/C code into C.  This
    lets us use a single source file for both 6c and gcc, handling
    the incompatible handling of return values.
    
    R=rsc
    DELTA=649  (613 added, 35 deleted, 1 changed)
    OCL=22682
    CL=22730

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

https://github.com/golang/go/commit/2b57a1124e87b0dc8bc1ff6899297b4d7d6e74f2

元コミット内容

Add cgo2c program to translate mixed Go/C code into C.  This
lets us use a single source file for both 6c and gcc, handling
the incompatible handling of return values.

変更の背景

Go言語の初期開発段階において、Goのランタイムや標準ライブラリの一部はC言語で記述されており、GoコードとCコードが混在する状況がありました。当時、Goには独自のCコンパイラである6c(64ビットアーキテクチャ向け)が存在し、これと一般的なgccコンパイラの両方でコードをコンパイルする必要がありました。

しかし、6cgccの間には、特に複数戻り値を持つ関数の呼び出し規約に関して非互換性が存在していました。Go言語の関数は複数の戻り値を返すことができますが、C言語の関数は通常単一の戻り値しか持ちません。CgoメカニズムがGoの複数戻り値をC側でどのように表現し、受け渡すかについて、コンパイラ間で異なるABI(Application Binary Interface)を採用していたため、問題が生じていました。

この非互換性のため、開発者は6cgccの両方でコンパイル可能なように、同じロジックを異なる方法で記述するか、条件付きコンパイル(#ifdefなど)を多用する必要がありました。これはコードの重複、保守性の低下、そして開発の複雑化を招いていました。

このコミットの目的は、この問題を解決し、GoとCの混在コードを単一のソースファイルで記述できるようにすることです。cgo2cというツールを導入することで、Goの関数シグネチャとCコードが混在する.cgoファイルを、6cgccのどちらでもコンパイル可能な標準的なCコードに変換し、コンパイラ間の戻り値の扱いの違いを吸収します。これにより、GoランタイムのC部分のコードベースを簡素化し、保守性を向上させることが可能になりました。

前提知識の解説

Go言語のCgo

Cgoは、GoプログラムからC言語のコードを呼び出したり、C言語のコードからGoの関数を呼び出したりするためのGo言語の機能です。Goのソースファイル内にimport "C"という特殊なインポート文を記述し、その後にC言語のコードを直接埋め込むことで、GoとCの相互運用を可能にします。Cgoは、GoとCの異なる型システムやメモリ管理、関数呼び出し規約の間の橋渡しを行います。

6c (Goの内部Cコンパイラ)

6cは、Go言語の初期のツールチェーンに含まれていたCコンパイラの一つです。Goプロジェクトは、独自のコンパイラ群(6g for Go, 6c for C, 6a for assemblerなど)を持っていました。これらはGo言語の特定のニーズに合わせて設計されており、クロスコンパイルの容易さや、Goランタイムとの密接な連携を可能にしていました。しかし、6cは標準的なCコンパイラ(GCCなど)とは異なる挙動や最適化を行うことがあり、特にABI(Application Binary Interface)の面で非互換性が生じることがありました。

GCC (GNU Compiler Collection)

GCCは、C、C++、Objective-C、Fortran、Ada、Goなどの多くのプログラミング言語をサポートする、広く使われているコンパイラコレクションです。Go言語のプロジェクトでは、特定のプラットフォームや環境で6cが利用できない場合や、既存のCライブラリとの連携のためにgccを使用する必要がありました。

GoとCの関数呼び出し規約の違い(特に複数戻り値)

Go言語の大きな特徴の一つは、関数が複数の値を戻り値として返せることです。例えば、func foo() (int, error)のように記述できます。しかし、C言語の関数は通常、単一の戻り値しか持ちません。CgoがGoの複数戻り値をC側で扱う場合、いくつかの方法が考えられます。

  • 構造体による戻り値: 複数の戻り値をCの構造体としてまとめ、その構造体を返す。
  • ポインタ引数による戻り値: 戻り値を格納するためのポインタを引数として渡し、関数内でそのポインタが指すメモリに値を書き込む。

6cgccは、これらのアプローチにおいて異なるABIを採用していたため、同じGoの関数シグネチャから生成されるCの関数定義が異なり、直接的な相互運用が困難でした。このコミットは、この歴史的な非互換性に対処するために導入されました。

.cgoファイルとプリプロセッサ/トランスレータ

このコミットで導入される.cgoファイルは、Goの関数シグネチャとC言語のコードブロックを組み合わせた特殊な形式のソースファイルです。cgo2cは、この.cgoファイルを読み込み、Goの関数シグネチャをC言語の関数プロトタイプと定義に変換し、埋め込まれたCコードをそのまま出力するプリプロセッサ(またはトランスレータ)として機能します。これにより、Goの複数戻り値の概念をCの構造体やポインタ引数にマッピングする処理をcgo2cが担当し、最終的に生成されるCファイルは6cgccのどちらでも正しくコンパイルできるようになります。

技術的詳細

cgo2cプログラムは、標準入力から.cgoファイルを読み込み、標準出力にC言語のソースコードを出力するシンプルなコマンドラインツールです。その主な機能は以下の通りです。

  1. Goパッケージ名の読み込み: .cgoファイルの先頭にあるpackage PACKAGENAMEを読み込み、C言語の関数名にGoのパッケージ名をプレフィックスとして付与するために使用します(例: package·functionName)。
  2. プリプロセッサディレクティブのコピー: # lineのようなプリプロセッサディレクティブをそのまま出力します。
  3. Go関数シグネチャの解析:
    • func NAME([NAME TYPE { , NAME TYPE }]) [(NAME TYPE { , NAME TYPE })] { の形式で記述されたGoの関数定義を解析します。
    • 関数名、引数リスト、戻り値リストを抽出します。
    • Goの型(例: *byte)をCの型(例: byte *)に変換します。
  4. C言語関数定義の生成:
    • 6c向け: void\npackage·name(param1 type1, param2 type2, ...) の形式で関数を定義します。Goの複数戻り値は、Cの引数リストの末尾にポインタとして追加されます。関数本体のCコードの後に、戻り値のポインタをフラッシュするFLUSHマクロが挿入されます。
    • gcc向け: Goの複数戻り値がある場合、それらを格納するためのCのstruct型を定義します(例: struct package_name_ret { type1 name1; type2 name2; };)。関数は、この構造体を戻り値として返すように定義されます。Goの関数名とCの関数名をasmキーワードでマッピングします(例: void package_name() asm ("package.name");)。
  5. Cコードブロックのコピー: Go関数シグネチャの後に続くCコードブロック({...}で囲まれた部分)を、ネストされたブレース、コメント、文字列リテラルを正しく処理しながら、そのまま出力します。これにより、Goの関数内でCのロジックを自由に記述できます。
  6. コマンドライン引数によるコンパイラ選択: cgo2c--6gまたは--gccというコマンドライン引数を受け取り、どちらのコンパイラ向けのCコードを生成するかを切り替えます。これにより、ビルドシステムが適切なコンパイラに合わせてcgo2cの出力を調整できます。

このメカニズムにより、Goのランタイムコードは、Goの複数戻り値のセマンティクスを維持しつつ、6cgccの両方でコンパイル可能な単一のCソースファイルとして記述できるようになりました。

src/runtime/Makefileの変更は、このcgo2cツールのビルドと利用をビルドプロセスに組み込むものです。

  • cgo2c: cgo2c.c ルールが追加され、cgo2c.cからcgo2c実行ファイルをビルドします。
  • %.c: %.cgo cgo2c ルールが追加され、.cgoファイルがcgo2cによって対応する.cファイルに変換されるようにします。
  • cleanターゲットにcgo2cの削除が追加されます。

src/runtime/malloc.cからGo関数スタブが削除され、それらがsrc/runtime/malloc_go.cgoに移行されたのは、malloc関連のGoとCの混在コードをcgo2cの管理下に置くためです。これにより、mallocのGoインターフェースが、cgo2cによって生成されるCコードを介して、6cgccの両方で一貫して動作するようになります。

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

このコミットの主要な変更は以下のファイルに集中しています。

  • src/runtime/cgo2c.c (新規追加): cgo2cプログラムのC言語ソースコード。GoとCの混在コードをCコードに変換するロジックが実装されています。
  • src/runtime/Makefile (変更): cgo2cのビルドと、.cgoファイルを.cファイルに変換するルールが追加されました。
  • src/runtime/malloc.c (変更): malloc_Alloc, malloc_Free, malloc_Lookup, malloc_GetStatsといったGo関数スタブが削除されました。これらの機能はcgo2cを介して提供されるようになります。
  • src/runtime/malloc.h (変更): malloc, free, mlookupの関数プロトタイプが追加されました。
  • src/runtime/malloc_go.cgo (新規追加): malloc関連のGo関数とCコードを混在させた新しいソースファイル。cgo2cによって処理されます。

コアとなるコードの解説

src/runtime/cgo2c.c

このファイルは、Goの関数シグネチャとCコードを解析し、ターゲットコンパイラ(6cまたはgcc)に応じたCコードを生成する主要なロジックを含んでいます。

  • main関数:
    • コマンドライン引数--6gまたは--gccを解析し、flag_gccを設定します。
    • process_file関数を呼び出し、ファイル全体の処理を開始します。
  • process_file関数:
    • read_package()でGoのパッケージ名を読み込みます。
    • read_preprocessor_lines()でプリプロセッサディレクティブをコピーします。
    • ループ内でread_func_header()を呼び出し、Goの関数定義を一つずつ解析します。
    • 解析した関数情報(名前、引数、戻り値)に基づいて、write_func_header()でCの関数ヘッダを生成します。
    • copy_body()でGo関数内のCコードブロックをコピーします。
    • write_func_trailer()でCの関数トレーラ(戻り値の処理など)を生成します。
    • 解析したメモリを解放します。
  • read_token / read_token_no_eof:
    • 入力ストリームからトークン(識別子、区切り文字など)を読み込みます。
    • コメント(///* */)をスキップするロジックが含まれています。
  • read_type:
    • Goの型表現(例: *byte)をCの型表現(例: byte *)に変換します。ポインタの数を正しく処理します。
  • read_params:
    • Goの関数引数または戻り値のリストを解析し、名前と型のペアのリンクリストとして返します。
  • read_func_header:
    • funcキーワードから始まり、関数名、引数リスト、戻り値リスト、そして{までのGo関数シグネチャを解析します。
  • write_6g_func_header / write_6g_func_trailer:
    • 6cコンパイラ向けのC関数ヘッダとトレーラを生成します。Goの複数戻り値は、Cの引数として渡されるポインタとして扱われ、トレーラでFLUSHマクロが呼び出されます。
  • define_gcc_return_type / write_gcc_return_type / write_gcc_func_header / write_gcc_func_trailer:
    • gccコンパイラ向けのC関数ヘッダとトレーラを生成します。
    • Goの複数戻り値がある場合、それらをカプセル化するためのCのstruct型を定義し、関数はその構造体を戻り値として返します。
    • asmキーワードを使用して、Goの関数名とCの関数名をマッピングします。
  • copy_body:
    • Go関数定義内のCコードブロックを、ブレースのネストレベルを考慮しながら、そのまま出力します。文字列リテラルやコメント内のブレースを誤って解釈しないように注意深く処理されます。

src/runtime/malloc_go.cgo

このファイルは、cgo2cによって処理されるGoとCの混在コードの具体例です。

package malloc
#include "runtime.h"
#include "malloc.h"

func Alloc(n uintptr) (p *byte) {
	p = malloc(n);
}

func Free(p *byte) {
	free(p);
}

func Lookup(p *byte) (base *byte, size uintptr) {
	mlookup(p, &base, &size);
}

func GetStats() (s *MStats) {
	s = &mstats;
}

このファイルでは、mallocパッケージのGo関数Alloc, Free, Lookup, GetStatsが定義されています。それぞれのGo関数の中身はC言語のコードで記述されており、malloc, free, mlookupといったCの関数を呼び出しています。特にLookup関数はbasesizeという2つの戻り値を持っており、cgo2cがこれを6cgccの両方で正しく扱えるCコードに変換する役割を担います。

関連リンク

特になし。

参考にした情報源リンク

  • Go言語のCgoに関する公式ドキュメント (現在のCgoの動作は、このコミット当時のものとは異なる可能性があります)
  • Go言語の初期のコンパイラに関する議論やドキュメント (当時の情報を見つけるのは困難なため、一般的なCgoの概念に限定)
  • GCCのABIに関する一般的な情報
  • cgo2c.cのソースコード自体の詳細な分析
  • Go language 6c compiler vs gcc return value incompatibility - Google Search