43
コココココココ コ 1 コ (2011/10/06) ココ コ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ コココ ココ ココ ココ ココ ココ ココ ココ ココ ココ ココ コココ

コンパイラ演習 第 1 回 (2011/10/06)

Embed Size (px)

DESCRIPTION

コンパイラ演習 第 1 回 (2011/10/06). 中村 晃一 野瀬 貴史  前田 俊行 秋山 茂樹 池尻 拓朗 鈴木 友博 渡邊 裕貴 潮田 資秀 小酒井 隆広 山下 諒蔵 佐藤 春旗 大山 恵弘 佐藤 秀明 住井 英二郎. プロセッサ・コンパイラ実験 全体 の大目標. 計算機システム を作る 計算機システムが ( ハードもソフトも ) “black box” でないことを身をもって学ぶ. プロセッサ・コンパイラ実験 全体の進め方. 班 (4〜5 人程度 ?) に分かれて進める うち 1 人をコンパイラ係とする 具体的には以下を作成する - PowerPoint PPT Presentation

Citation preview

Page 1: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラ演習第 1 回

(2011/10/06)中村 晃一 野瀬 貴史 前田 俊行

秋山 茂樹 池尻 拓朗鈴木 友博 渡邊 裕貴

潮田 資秀小酒井 隆広

山下 諒蔵 佐藤 春旗大山 恵弘 佐藤 秀明

住井 英二郎

Page 2: コンパイラ演習 第  1  回 (2011/10/06)

プロセッサ・コンパイラ実験全体の大目標

•計算機システムを作る– 計算機システムが ( ハードもソフトも )

“black box” でないことを身をもって学ぶ

Page 3: コンパイラ演習 第  1  回 (2011/10/06)

プロセッサ・コンパイラ実験全体の進め方

• 班 (4 〜 5 人程度 ?) に分かれて進める– うち 1 人をコンパイラ係とする

• 具体的には以下を作成する– 自作 CPU の設計・実装– 自作 CPU 向けのコンパイラ ( クロスコンパイ

ラ )– etc.

• レイトレーシングプログラムを正しく動作させることが条件

Page 4: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラ係の目標

•自作 CPU 向けのコンパイラを実装する

Page 5: コンパイラ演習 第  1  回 (2011/10/06)

演習の進め方• 毎回講義を 15 〜 45 分ほど行う– 対象言語 : OCaml もどき– 記述言語 : OCaml

• あとは各自で演習してもらう– コンパイラを実装する、課題を解く等

• 講義資料等は以下に置いておきます– http://www.yl.is.s.u-tokyo.ac.jp

/wiki/lectures/CompilerEnshu2011.ja

Page 6: コンパイラ演習 第  1  回 (2011/10/06)

お手本とするコンパイラ• 「美しい日本の ML コンパイラ」 ( 通称

MinCaml)• 作者 : 住井 英二郎

– 対象言語 : OCaml もどき– 記述言語 : OCaml– 対象 CPU: SPARC 、 PowerPC

– URL:http://min-caml.sourceforge.net/

Page 7: コンパイラ演習 第  1  回 (2011/10/06)

講義内容 ( 変更の可能性あり )

• コンパイラの概要 ( 今回 )• K 正規化、 α 変換、最適化• クロージャ変換• 仮想マシンコード生成• レジスタ割り当て• アセンブリ生成、末尾呼び出し最適化• ??????????????• ??????????????• ??????????????• ??????????????• ??????????????• ??????????????

基礎編

応用編

Page 8: コンパイラ演習 第  1  回 (2011/10/06)

課題について• 二種類の課題がある

– 共通課題• 全員が解くことを想定している課題

– コンパイラ係向け課題• コンパイラ係が解くことを想定している課題

Page 9: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラ係以外の人の単位取得条件

• 共通課題を 6 つ以上提出することかつ

• CPU 担当教員の出す条件をクリアすること

Page 10: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラ係の人の単位取得条件

• 自作 CPU ( またはシミュレータ ) 上でレイトレーシングプログラムが完動すること– MinCaml を改造する形でもよい

かつ• 共通課題を 6 つ以上提出すること

かつ• コンパイラ係向け課題を 1 つ以上提出するこ

とかつ

• CPU 担当教員の出す条件をクリアすること

Page 11: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラの概要

Page 12: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラとは• ある言語のプログラムを

他の言語に翻訳するシステム– gcc

• C アセンブリ– javac

• Java JVM bytecode

– ocamlc• OCaml OCaml VM bytecode

– ocamlopt• OCaml アセンブリ

– etc.

Page 13: コンパイラ演習 第  1  回 (2011/10/06)

コンパイルの例

let rec gcd m n = if m = 0 then n else if m <= n then gcd m (n - m) else gcd n (m - n)

.section ".text"gcd.7: cmp %i2, 0 bne be_else.17 nop mov %i3, %i2 retl nopbe_else.17: cmp %i2, %i3 bg ble_else.18 nop sub %i3, %i2, %i3 b gcd.7 nopble_else.18: sub %i2, %i3, %o5 mov %i3, %i2 mov %o5, %i3 b gcd.7 nop

ソースコード

アセンブリコード

Page 14: コンパイラ演習 第  1  回 (2011/10/06)

コンパイラの難しいところ言語間のギャップが大きい

• 変数• 関数・クロージャ• 式・文

• レジスタ・メモリ• ジャンプ・条件分岐• CPU 命令

ソースコード アセンブリコード

Page 15: コンパイラ演習 第  1  回 (2011/10/06)

解決法 : ちょっとずつ変換する

中間言語 1

• 変数• ジャンプ・条件分岐• 式・文

アセンブリ• レジスタ・メモリ• ジャンプ・条件分岐• CPU 命令

ソースコード• 変数• 関数・クロージャ• 式・文

中間言語 2

• 変数• ジャンプ・条件分岐• CPU 命令

クロージャ変換

仮想マシンコード生成

レジスタ割当て

概念図

Page 16: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

Page 17: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

字句解析

Page 18: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

構文解析

Page 19: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

型検査

Page 20: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

K 正規化

Page 21: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

α 変換

Page 22: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

最適化

Page 23: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

クロージャ変換

Page 24: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

仮想マシンコード生成

Page 25: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

レジスタ割当て

Page 26: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml ではこんな感じ(* main.ml *)let lexbuf outchan l = Id.counter := 0; Typing.extenv := M.empty; Emit.f outchan (RegAlloc.f (Simm13.f (Virtual.f (Closure.f (iter !limit (Alpha.f (KNormal.f (Typing.f (Parser.exp Lexer.token l)))))))))

アセンブリ生成

Page 27: コンパイラ演習 第  1  回 (2011/10/06)

字句解析・構文解析• 字句解析– 文字列をトークン ( 単語 ) の列に変換する

• 構文解析– トークン列を抽象構文木に変換する

• MinCaml では ocamllex 、 ocamlyacc を用いる– ML 演習第 4 回参照

Page 28: コンパイラ演習 第  1  回 (2011/10/06)

MinCaml の型検査• 基本的には ML の型推論– ML 演習第 6 回参照

• ただし、以下の点に注意–推論の実装に reference を用いている–未定義の変数があった場合に

「外部変数」とみなす–型多相はサポートしていない

Page 29: コンパイラ演習 第  1  回 (2011/10/06)

K 正規化• 計算途中の結果にも全て変数をつける– アセンブリに少し近づける–評価順序が少し明確になる

1 + 2 - 3 + 4 - 5

let a = 1 + 2 inlet b = a - 3 inlet c = b + 4 inlet d = c – 5 ind

Page 30: コンパイラ演習 第  1  回 (2011/10/06)

α 変換• 変数の名前をつけかえる

• 全ての変数が互いに異なる名前をもつようにする– 最適化やその後の処理が楽になる

let x = 1 inlet x = x + 1 inx

let x0 = 1 inlet x1 = x0 + 1 inx1

Page 31: コンパイラ演習 第  1  回 (2011/10/06)

最適化• MinCaml では

以下の 3 つの処理を繰り返し行っている– インライン展開– 定数たたみこみ–不要定義削除

• 他にも最適化の手法はたくさんあるので自分で色々試してみるとよい

Page 32: コンパイラ演習 第  1  回 (2011/10/06)

クロージャ変換• ネストした関数定義を平らにする

let f a = let g b = a + b in g 3

let g a b = a + blet f a = g a 3

超大雑把な図式

実際には MinCaml では

a はクロージャを介して

渡される

Page 33: コンパイラ演習 第  1  回 (2011/10/06)

仮想マシンコード生成• よりアセンブリに近い形式に変換する

• 実際のアセンブリとの違い– レジスタは無限個ある– if 式や関数呼出しがある

– タプルやクロージャ、配列の操作をメモリロード・ストア命令の組み合わせに変換する

Page 34: コンパイラ演習 第  1  回 (2011/10/06)

レジスタ割当て• 仮想マシンコードのレジスタに

実際のレジスタを割り当てる

– MinCaml ではそれ程複雑なことはしていない• そこそこの速さ & そこそこの易しさ

– MinCaml で性能を出すためにはここの改造は必須の予感

Page 35: コンパイラ演習 第  1  回 (2011/10/06)

アセンブリ生成• 実際のアセンブリを出力する– ここでようやく関数呼出しや if 式を

実際の命令に変換している• 加えて末尾呼出しの最適化をしている

– ループ最適化を頑張りたい場合にはここではちょっと遅いかも ?

Page 36: コンパイラ演習 第  1  回 (2011/10/06)

課題

Page 37: コンパイラ演習 第  1  回 (2011/10/06)

共通課題

• 今回は全 3問のうちどれかを解けばよい

– もちろん全部解いてもよい

Page 38: コンパイラ演習 第  1  回 (2011/10/06)

共通課題 その 1

• MinCaml を改造し Syntax.t や KNormal.t などの値を出力できるようにせよ

• 出力の形式や方法は問わないが真面目にやればデバッグのとき役に立つかも

• 例えば以下のような感じ

(* test/fib.ml *)let rec fib n = if n <= 1 then 1 else fib (n-1) + fib (n-2) inprint_int(fib 30)

…If LE Var(n) Int(1) Int(1) Add…

入力

出力

Page 39: コンパイラ演習 第  1  回 (2011/10/06)

共通課題 その 2

• MinCaml を改造しパースエラー時および型エラー時にどの箇所 ( 例 : 行番号や列番号等 )に問題があったかを表示するようにせよ

Page 40: コンパイラ演習 第  1  回 (2011/10/06)

共通課題 その 3

• MinCaml を改造し出力されたアセンブリのどの命令が入力されたソースのどの式に対応するかを判別できるようにせよ– 例えば、対応を表すファイルを

コンパイル時に生成するなど

Page 41: コンパイラ演習 第  1  回 (2011/10/06)

課題の提出先と締切• 提出先 : [email protected]

– 質問等は [email protected] まで

• 締切 : 2 週間後 (10/20) の午後 1 時( JST)– コンパイラ係向け課題の締切は 2012年 2月 28 日

• Subject は Report < 課題番号 > < 学籍番号 :5桁 > とすること– 例 : Report 1 11099

• 間にスペースを 1 つずついれること

• メールの本文にも氏名と学籍番号を明記すること– 正常に受理されれば

通知メールが届くはずなので確認してください

Page 42: コンパイラ演習 第  1  回 (2011/10/06)

課題提出についての注意• プログラムだけでなく説明・実行例・考察なども書くこと

• 基本的にはメール本文に解答を記述すること

– ただし、多くのソースコードを送る必要がある場合にはtar などで固めて提出してよい

Page 43: コンパイラ演習 第  1  回 (2011/10/06)

謝辞• 本講義では、昨年度までの講義を担当さ

れた以下の方々によって書かれた資料の多くを再利用させていただいております。ここに感謝いたします。

住井英二郎先生、大山恵弘先生、佐藤秀明氏、山下諒蔵氏、佐藤春旗氏、

小酒井隆広氏、潮田資秀氏、鈴木友博氏、渡邊裕貴氏、秋山 茂樹氏、池尻 拓朗氏