言語処理ツール

このページでは、コンパイラやインタプリタなどの言語プロセッサの種類、コンパイルの5段階と最適化、リンクとライブラリ、makeがわかります。

  • 一言で言うと:
    • 人間が書いたプログラム(ソース)を、コンピュータが実行できる形にするまでの道具と手順の話。「翻訳する(コンパイラなど)」→「速く小さくする(最適化)」→「部品をつなぐ(リンク)」の流れ。

翻訳の道具いろいろ(言語プロセッサ)→ 翻訳の手順と工夫(コンパイル技法)→ 部品をつないで完成させる(リンク)

覚え方の軸

  • 言語プロセッサは「何から何へ変換するか」「いつ翻訳するか」で分ける:
    • アセンブリ言語 → 機械語(アセンブラ)、高水準言語 → 機械語をまとめて(コンパイラ)、1命令ずつ翻訳しながら実行(インタプリタ)、高水準言語 → 別の高水準言語(プリプロセッサ)
  • コンパイラの手順は5段階、順番ごと覚える:
    • 字句解析(単語に切る)→ 構文解析(文法チェック)→ 意味解析(意味と型のチェック、中間コード)→ 最適化 → コード生成
  • 最適化は「速くする」か「小さくする」か:
    • 速く=計算を軽くする・呼出しやループを減らす、小さく=ムダを削る・共通部分をまとめる、両方=レジスタ割付・定数の畳込み
  • ライブラリは「いつつなぐか」で分ける:
    • 実行前につなぐ(静的)⇔ 実行時につなぐ(動的・共有)
  • 「本物か、まねか」:
    • シミュレータ(ソフトで再現)⇔ エミュレータ(ハードで内部動作まで再現)

言語プロセッサ:プログラムを翻訳する道具

  • 原始プログラム(ソースプログラム、ソースコード):
    • プログラミング言語で書いたプログラム。そのままでは実行できないので、変換する
  • 言語プロセッサ:
    • 原始プログラムを別の形に変換するソフトウェアの総称
  • 主要な言語プロセッサ
名前 何をする?
アセンブラ アセンブリ言語のプログラムを機械語に翻訳する
コンパイラ 高水準言語のプログラムをまとめてコンパイル(翻訳)し、機械語の目的プログラムを作る
インタプリタ 命令を1つずつ解釈し、そのつど翻訳しながら実行する(目的プログラムは作らない)
プリプロセッサ ある高水準言語のプログラムを、別の高水準言語のプログラムに変換する。または、高水準言語に追加で定義した命令を、もとの高水準言語だけのプログラムに直す
  • 例え:
    • コンパイラは「本を丸ごと翻訳してから渡す翻訳家」、インタプリタは「1文ずつその場で訳す同時通訳」
  • 高水準言語:
    • 特定のコンピュータアーキテクチャに依存せず、効率よくプログラムを書ける言語
  • コンパイラの2種類
    • セルフコンパイラ:
      • 今使っているコンピュータ(または同じアーキテクチャのコンピュータ)で実行できる目的プログラムを作る
    • クロスコンパイラ:
      • 異なるアーキテクチャ(命令形式が違う)のコンピュータ用の目的プログラムを作る
  • セルフ開発:
    • ソフトウェアを実行する機器と同じ機器で開発すること
  • クロス開発:
    • 実行する機器とは別の開発専用の機器で開発すること(例:携帯電話用のプログラムをパソコンで開発する)
  • その他の言語プロセッサ
    • ジェネレータ(生成系):
      • 手続を書かなくても、入力・処理・出力の条件を引数(パラメータ)で指定するだけで、プログラムを自動生成する
      • UNIX系の字句解析ツールLexや、構文解析ツールYaccもジェネレータ
      • ドキュメンテーションジェネレータ:
        • ソースコード中の決まった形式のコメント文などから、プログラムのドキュメントを生成する。コードとドキュメントの一貫性を保ち、開発効率を上げる
    • シミュレータ(実行系):
      • 他のコンピュータ用のプログラムの命令を、解読しながら実行する。開発用のコンピュータで、ターゲットコンピュータの動きをソフト的に再現するだけ
    • エミュレータ:
      • シミュレータと同じことをハードウェア(マイクロプログラム)で行うもの。内部動作まで模擬的に再現する

コンパイル技法:コンパイラは5段階で翻訳する

  • コンパイラの処理手順★:
    • ソースプログラム(原始プログラム)→ 字句解析 → 構文解析 → 意味解析 → 最適化 → コード生成 → 目的プログラム(オブジェクトプログラム)
    • 例え:
      • 英文和訳で、「単語に区切る(字句)→ 文法が正しいか見る(構文)→ 意味が通るか見る(意味)→ 訳を読みやすく整える(最適化)→ 清書する(コード生成)」
段階 やること
字句解析 文字の列を、変数名・演算子・予約語・定数・区切り記号などの、意味を持つ最小単位である字句(トークン)の列に分解する
構文解析 トークンを言語の構文規則に従って解析し、正しい文かを判定する。誤りがあれば文法エラー
意味解析 変数の宣言と使用の対応付けや、演算のデータ型の整合性チェックを行う。文の意味を解釈し、同じ意味の別の表現に直す。一般に、3つ組み、4つ組み、逆ポーランドなどによる中間コードを作る
最適化 処理時間や容量が少なくなるよう、変数のレジスタ割付や、不要な演算の省略などのプログラム変換(再編成)を行う
コード生成 目的プログラムとして出力するコードを作る
  • コンパイラの最適化手法(コンパイラに最適化レベルを指定できる)
    • 実行速度からみた最適化(実行時間を短くする)
      • べき乗は乗算に、乗算は加算に変換する(例:x² → x×x、x×2 → x+x)
      • ずっと更新されない変数は、定数で置き換える
      • 関数のインライン展開:
        • 関数を呼ぶ場所に、呼ばれる関数の中身を取り込んで、呼出し時間を節約する
      • ループの中で値が変わらない式は、ループの外に出す
      • ループアンローリング(ループ展開):
        • ループの中の繰返し処理を展開して、毎回の終了判定の回数を減らす
        • 例:
          • 二重ループの内側を展開して一重ループにする。配列の初期化で、1回のループで複数の要素を初期化してループ回数を減らす(100回ループ → 1回で4個ずつ初期化すれば25回)
    • コードサイズからみた最適化(プログラムを小さくする)
      • プログラムの冗長部分や不要・無用命令を取り除く
      • 変数の初期値や定数に共通部分があればまとめる
    • 実行速度とコードサイズの両方からみた最適化
      • 変数をレジスタに割り当てる
      • 定数の畳込み:
        • 定数どうしの計算式を、計算結果で置き換える(例:x=1+2 を x=3 にする)

リンク(連係編集):部品をつないで実行できる形にする

  • リンク(連係編集):
    • コンパイラが作った目的プログラム(オブジェクトプログラム)に、使っているライブラリモジュールなど実行に必要なものをまとめ上げて、実行可能なプログラム(ロードモジュール)にすること
  • リンカ:
    • リンクを行うプログラム
  • ロードモジュール(実行ファイル):
    • ローダによって主記憶にロードされ、実行される
  • ライブラリ:
    • 多くのプログラムが共通に使う機能を部品にして、まとめたファイル
  • ライブラリの分類(リンクのタイミングと共有性で分ける)
種類 リンクするタイミング 特徴
静的ライブラリ 実行前(リンク時)に、各プログラムにリンクされる 他のプログラムと共有できない
動的ライブラリ 実行時に、必要に応じてリンク(マップ)して使う 主記憶にロードされ、複数のプログラムから同時に使えるので、主記憶の使用効率がよい
共有ライブラリ プログラム起動時に主記憶にロードされ、その後は他のプログラムからも使える UNIX系OSでは、動的ライブラリと区別される
  • 静的リンクの例:
    • main.c と sub.c をそれぞれコンパイル → main.o と sub.o → リンカが静的ライブラリと一緒にまとめる → ロードモジュール app
  • make(コンパイル・リンクの自動化ツール):
    • ソースプログラム、目的プログラム、実行ファイルの間の依存関係と、各ファイルの作り方を書いたmakeファイル(makefile)をもとに、コンパイルが必要なファイルを求め、最小の手順で実行ファイルを作る
    • 修正するたびに全部をコンパイルするムダを省ける
    • 例:
      • makefileに「app は main.o と sub.o に依存」「main.o は main.c に依存」「sub.o は sub.c に依存」と書いておく → sub.c だけ直したなら、sub.c だけをコンパイルして app を作り直す
    • cc:
      • C言語コンパイラ。オプション「-o」で実行ファイルを作り、「-c」でコンパイルだけを行う。ライブラリのリンクを静的/動的のどちらにするかも指定できる

混同しやすいペア

  • コンパイラ(まとめて翻訳してから実行)/インタプリタ(1命令ずつ翻訳しながら実行)
  • アセンブラ(アセンブリ言語 → 機械語)/コンパイラ(高水準言語 → 機械語)/プリプロセッサ(高水準言語 → 別の高水準言語)
  • セルフコンパイラ(同じアーキテクチャ用)/クロスコンパイラ(違うアーキテクチャ用)
  • セルフ開発(実行する機器で開発)/クロス開発(別の機器で開発)
  • シミュレータ(ソフトで動きを再現)/エミュレータ(ハードで内部動作まで再現)
  • 字句解析(トークンに切る)/構文解析(文法が正しいか)/意味解析(型のチェック、中間コード)
  • インライン展開(関数呼出しをなくす)/ループアンローリング(ループの終了判定を減らす)/定数の畳込み(1+2を3にしておく)
  • 静的ライブラリ(実行前にリンク。共有できない)/動的ライブラリ(実行時にリンク。共有できて主記憶の効率がよい)
  • リンカ(部品をつないでロードモジュールを作る)/ローダ(ロードモジュールを主記憶に載せる)
  • cc -c(コンパイルだけ)/cc -o(実行ファイルを作る)

← 05 ソフトウェアの目次に戻る

タイトルとURLをコピーしました