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

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

このコミットは、Go言語プロジェクトの初期段階において、Plan 9およびInfernoオペレーティングシステムのツールチェインである8a(アセンブラ)、8c(Cコンパイラ)、8l(リンカ)をインポートしたものです。これにより、Go言語のブートストラッププロセス、特に初期のコンパイラとランタイムの構築に必要な基盤が提供されました。大量のファイル追加(19539行)が示唆するように、これはGoのビルドシステムに不可欠なコンポーネントを導入する重要なステップでした。

コミット

Author: Russ Cox rsc@golang.org Date: Tue Jan 6 09:41:38 2009 -0800

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

https://github.com/golang/go/commit/4dee747fb949b44262af5b7b3161e64fa720578a

元コミット内容

    8a, 8c, and 8l from inferno distribution
    
    R=r
    DELTA=19539  (19539 added, 0 deleted, 0 changed)
    OCL=22109
    CL=22109

変更の背景

Go言語は、その設計思想においてBell LabsのPlan 9オペレーティングシステムから多大な影響を受けています。Plan 9は、UNIXの後継として設計され、シンプルさ、モジュール性、ネットワーク透過性、そして「すべてがファイルである」という哲学を特徴としていました。Inferno OSは、Plan 9のアイデアをさらに発展させ、分散システムやポータビリティに焦点を当てたものです。

Go言語の初期開発において、既存のC言語ベースのツールチェインを利用してGoコンパイラ自体をコンパイルする「ブートストラップ」が必要でした。このコミットは、そのブートストラッププロセスを可能にするために、Inferno OSで使われていたx86アーキテクチャ(80386)向けのアセンブラ(8a)、Cコンパイラ(8c)、およびリンカ(8l)をGoプロジェクトに導入しました。これにより、Go言語のコンパイラやランタイムの初期バージョンをビルドするための基盤が確立され、Go言語の自己ホスト型コンパイラへの道が開かれました。

前提知識の解説

Plan 9 from Bell Labs

Plan 9は、Bell Labsが開発した分散オペレーティングシステムです。その主な特徴は以下の通りです。

  • 「すべてがファイルである」哲学: プロセス、ネットワーク接続、デバイスなど、システム内のあらゆるリソースがファイルとして表現され、標準的なファイルI/O操作でアクセスできます。
  • Namespace: 各プロセスは独自のファイルシステムビュー(namespace)を持ち、リソースを柔軟にマウント・アンマウントできます。
  • UTF-8: システム全体でUTF-8が採用され、多言語対応が組み込まれています。
  • シンプルさとモジュール性: 小さなツールを組み合わせて複雑なタスクを実行するUNIXの哲学をさらに推し進めました。

Inferno OS

Infernoは、Plan 9の設計原則に基づき、分散コンピューティング環境向けに開発されたオペレーティングシステムです。

  • ポータビリティ: 仮想マシン(Dis VM)上で動作し、様々なハードウェアやOS上で実行可能です。
  • Limbo言語: Infernoのアプリケーション開発に用いられたプログラミング言語です。
  • 分散システム: ネットワークを介したリソース共有と分散アプリケーションの構築に特化しています。

8a, 8c, 8l (Plan 9/Inferno ツールチェイン)

Plan 9およびInfernoのツールチェインは、ターゲットアーキテクチャを示す数字(例: 8はx86、6はAMD64、5はARMなど)とツール名(aはアセンブラ、cはCコンパイラ、lはリンカ)を組み合わせた命名規則を持っています。

  • 8a (Assembler): x86アーキテクチャ向けのアセンブラです。アセンブリ言語のソースコードを機械語のオブジェクトファイルに変換します。Go言語の初期のランタイムや一部の低レベルなコードはアセンブリ言語で書かれており、このツールがそれらをコンパイルするために必要でした。
  • 8c (C Compiler): x86アーキテクチャ向けのCコンパイラです。Go言語の初期のコンパイラ自体はC言語で書かれており、この8cがそのコンパイルに使用されました。
  • 8l (Linker): x86アーキテクチャ向けのリンカです。コンパイルされたオブジェクトファイル(アセンブリコードやCコードから生成されたもの)を結合し、実行可能なバイナリファイルを生成します。シンボル解決やアドレスの再配置などを行います。

Go言語の初期開発とPlan 9の影響

Go言語は、Rob Pike、Ken Thompson、Robert GriesemerといったPlan 9の開発に深く関わったエンジニアによって設計されました。そのため、Go言語にはPlan 9の設計思想が色濃く反映されています。

  • シンプルで実用的なツールチェイン: Goのビルドシステムは、Plan 9のツールチェインと同様に、シンプルで高速なコンパイルを重視しています。
  • 並行性: GoのGoroutineとChannelは、Plan 9のCSP(Communicating Sequential Processes)に影響を受けています。
  • モジュール性: Goのパッケージシステムは、Plan 9のモジュール性の概念と共通点があります。
  • ガベージコレクション: Plan 9のシステムプログラミング言語であるAlefやLimboもガベージコレクションを持っていました。

このコミットは、Go言語がそのルーツであるPlan 9/Infernoの技術的遺産をどのように活用して初期の基盤を築いたかを示す具体的な例です。

技術的詳細

このコミットで導入された8a, 8c, 8lは、それぞれアセンブラ、Cコンパイラ、リンカとしての標準的な機能を提供します。

8a (アセンブラ)

8aは、x86アセンブリ言語のソースコードを解析し、オブジェクトファイルを生成します。

  • 字句解析 (lex.c): アセンブリコードをトークン(命令、レジスタ、シンボル、定数など)に分割します。
  • 構文解析 (a.y): トークンのストリームを解析し、アセンブリ言語の文法規則に従っているかを確認します。a.yはYacc/Bisonの文法定義ファイルであり、アセンブリ命令の構造やオペランドの形式を定義しています。
  • コード生成: 解析されたアセンブリ命令を対応する機械語のバイトコードに変換し、オブジェクトファイルに書き出します。

8c (Cコンパイラ)

8cは、C言語のソースコードをx86機械語にコンパイルします。

  • フロントエンド:
    • 字句解析: Cソースコードをトークンに分割します。
    • 構文解析: トークンから抽象構文木(AST)を構築します。
    • 意味解析: 型チェック、シンボル解決などを行い、ASTに意味的な情報を付加します。
  • バックエンド:
    • 中間表現生成: ASTを中間表現(IR)に変換します。
    • 最適化: IRに対して様々な最適化(peephole optimizationなど)を適用し、生成されるコードの効率を向上させます。peep.cはこの部分を担当します。
    • コード生成 (cgen.c, cgen64.c): IRをターゲットアーキテクチャ(x86)の機械語に変換します。cgen.cは32ビットコード生成、cgen64.cは64ビットコード生成に関連する可能性があります。
    • レジスタ割り当て (reg.c): 変数や中間結果を効率的にレジスタに割り当てます。

8l (リンカ)

8lは、8a8cによって生成された複数のオブジェクトファイルを結合し、実行可能なバイナリファイルを生成します。

  • シンボル解決: 異なるオブジェクトファイル間で参照されるシンボル(関数名、変数名など)を解決し、それらのアドレスを決定します。
  • 再配置: オブジェクトファイル内の相対アドレスを、最終的な実行可能ファイル内の絶対アドレスに調整します。
  • セクション結合: コード、データ、BSSなどの異なるセクションを結合し、実行可能ファイルのレイアウトを決定します。

これらのツールは、Go言語の初期のコンパイラ(C言語で書かれていた)をコンパイルし、Goランタイムの低レベルな部分(アセンブリ言語で書かれた部分)を処理するために不可欠でした。これにより、Go言語は自己ホスト型コンパイラへの移行を進めることができました。

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

このコミットでは、以下の25個のファイルが新規追加されています。これらはすべて、Inferno OSの8a (アセンブラ)、8c (Cコンパイラ)、8l (リンカ) のソースコードです。

  • src/cmd/8a/a.h: 8aアセンブラのヘッダファイル。データ構造や定数、関数プロトタイプを定義。
  • src/cmd/8a/a.y: 8aアセンブラのYacc/Bison文法定義ファイル。アセンブリ言語の構文規則を定義。
  • src/cmd/8a/l.s: 8aアセンブラの低レベルなアセンブリコード。システムコールや初期化ルーチンなど。
  • src/cmd/8a/lex.c: 8aアセンブラの字句解析器。アセンブリコードをトークンに分割。
  • src/cmd/8c/8.out.h: 8cコンパイラと8lリンカが共有するオブジェクトファイルフォーマットの定義。
  • src/cmd/8c/cgen.c: 8cコンパイラのコード生成部分。一般的なコード生成ロジック。
  • src/cmd/8c/cgen64.c: 8cコンパイラの64ビットコード生成部分。
  • src/cmd/8c/div.c: 8cコンパイラの除算関連のコード。
  • src/cmd/8c/gc.h: 8cコンパイラのガベージコレクション関連のヘッダファイル(ただし、この文脈ではコンパイラ内部のメモリ管理に関連する可能性が高い)。
  • src/cmd/8c/list.c: 8cコンパイラのリスト処理関連のコード。
  • src/cmd/8c/machcap.c: 8cコンパイラの機械能力(machine capabilities)関連のコード。
  • src/cmd/8c/mkenam: 8cコンパイラで使用される列挙型を生成するスクリプトまたは定義。
  • src/cmd/8c/mul.c: 8cコンパイラの乗算関連のコード。
  • src/cmd/8c/peep.c: 8cコンパイラのpeephole最適化部分。
  • src/cmd/8c/reg.c: 8cコンパイラのレジスタ割り当て部分。
  • src/cmd/8c/sgen.c: 8cコンパイラの構造体生成関連のコード。
  • src/cmd/8c/swt.c: 8cコンパイラのswitch文処理関連のコード。
  • src/cmd/8c/txt.c: 8cコンパイラのテキストセクション(コード)生成関連のコード。
  • src/cmd/8l/asm.c: 8lリンカのアセンブリコード処理部分。
  • src/cmd/8l/l.h: 8lリンカのヘッダファイル。
  • src/cmd/8l/list.c: 8lリンカのリスト処理関連のコード。
  • src/cmd/8l/obj.c: 8lリンカのオブジェクトファイル処理部分。
  • src/cmd/8l/optab.c: 8lリンカのオペレーションテーブル(命令セット情報)関連のコード。
  • src/cmd/8l/pass.c: 8lリンカのリンキングパス(複数回の処理)関連のコード。
  • src/cmd/8l/span.c: 8lリンカのセクション配置(span)関連のコード。

コアとなるコードの解説

このコミットで追加されたファイル群は、Go言語の初期のビルドシステムを支える重要なコンポーネントです。特に注目すべきは、8a/a.y8a/lex.c8c/cgen.c8c/peep.c8c/reg.c、そして8l/obj.cです。

  • src/cmd/8a/a.y: このファイルは、アセンブリ言語の文法を定義するYacc(またはBison)の入力ファイルです。アセンブラがアセンブリコードを正しく解釈し、機械語に変換するための基盤となります。例えば、命令のオペランドの数や型、アドレス指定モードなどがここで定義されます。
  • src/cmd/8a/lex.c: アセンブリ言語のソースコードを読み込み、トークンに分割する字句解析器の実装です。コメントのスキップ、識別子、数値、記号などの認識を行います。
  • src/cmd/8c/cgen.c: Cコンパイラの主要なコード生成ロジックが含まれています。抽象構文木(AST)をトラバースし、ターゲットアーキテクチャ(x86)の機械語命令を生成する役割を担います。関数の呼び出し規約、変数へのアクセス、制御フロー(if文、ループなど)の変換などがここで行われます。
  • src/cmd/8c/peep.c: Peephole最適化の実装です。これは、生成された機械語コードの小さなシーケンス(peephole)を検査し、より効率的な同等のシーケンスに置き換えることで、コードのパフォーマンスを向上させます。例えば、冗長なロード/ストア命令の削除や、より短い命令への置き換えなどが行われます。
  • src/cmd/8c/reg.c: レジスタ割り当てのロジックが含まれています。コンパイラは、プログラムの実行中に頻繁にアクセスされる値をCPUのレジスタに割り当てることで、メモリへのアクセスを減らし、実行速度を向上させます。このファイルは、どの値をどのレジスタに割り当てるかを決定するアルゴリズムを実装しています。
  • src/cmd/8l/obj.c: リンカがオブジェクトファイルを読み込み、解析する部分です。オブジェクトファイル内のシンボルテーブル、再配置情報、コードセクション、データセクションなどを処理し、それらを結合して最終的な実行可能ファイルを構築します。

これらのファイルは、Go言語の初期のコンパイラがC言語で書かれていた時代に、そのコンパイラ自身をビルドし、Goランタイムの低レベルな部分を処理するために不可欠なツールとして機能しました。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Plan 9 from Bell Labsの公式ウェブサイト
  • Inferno Operating Systemの公式ウェブサイト
  • Go言語の初期のコミット履歴と関連する議論
  • コンパイラとリンカの一般的な概念に関する情報源