Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Cp11

22 views

Published on

Computer System#11

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Cp11

  1. 1. 第11章 コンパイラ#2 : コード生成
  2. 2. これまでのお復習い コンパイラの構成は大きく分けて2つ (p.225の図を参照) ・ 構文解析器 ・ コード生成器
  3. 3. これまでのお復習い コンパイラの構成は大きく分けて2つ (p.225の図を参照) ・ 構文解析器 → 高級言語で書かれた1つ1つのワード(トークン)を categorize (第10章で実装済) ・ コード生成器 → categorizeされたトークンを中間言語(VMコード)に変換 (本章で作成)
  4. 4. コード生成器 2つに分けて実装する ・ シンボルテーブル ・ コード生成モジュール
  5. 5. コード生成器 2つに分けて実装する ・ シンボルテーブル → クラス変数 と ローカル変数 の情報を追加していく (前回に実装) ・ コード生成モジュール → 今回実装!
  6. 6. コード生成器 ・ シンボルテーブル ・ コード生成モジュール
  7. 7. シンボルテーブル 高級言語には多くの変数がでてくる → 1つ1つの変数を別のもの(識別子)として認識する必要がある → 各識別子の情報をテーブルに記録しておく! (名前、型、属性、番号)
  8. 8. シンボルテーブル 名前 型 属性 番号 a int static 0 b int field 0 c String argument 0 d int var 0
  9. 9. シンボルテーブル コンパイラはシンボルテーブルを参照しながら、各識別子のメモリ割 り当てを行う! 名前 型 属性 番号 a int static 0 b int field 0 c String argument 0 d int var 0 コンパイラ この識別子には、static セグメントの0番目を使 おう! この識別子には、argument セグメントの0番目を使お う!
  10. 10. コード生成器 ・ シンボルテーブル ・ コード生成モジュール
  11. 11. コード生成モジュール 高級言語をVM言語に変換するモジュール
  12. 12. コード生成モジュール 高級言語をVM言語に変換するモジュール ここでは、スタック形式で書かれる
  13. 13. スタックのお復習い スタックは、LIFO (Last In First Out) の性質を持つデータ構造 最後に入れたデータは最初に取り出される データ2 データ1 データ1 データ2 データ2 データ1
  14. 14. スタックのお復習い ・スタックにデータを入れることを push ・スタックからデータを取り出すことを pop データ2 データ1 データ2 データ1
  15. 15. VM言語とはどのような内容? VM言語 → メモリとスタック間のデータのやり取りを表す ・・・ 8 2 5 アドレス3 アドレス1 アドレス2 pop 8 push 5 メモリ (RAM) スタック
  16. 16. 高級言語からVM言語へどのように変換される? 次の5つに分けて考える! ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  17. 17. VM言語への変換 ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  18. 18. 変数操作の変換 numという (ローカル) 変数に 2 を代入 ・・・ 2 2 2 メモリ (RAM) スタック ローカル セグメントnum 2 スタック
  19. 19. 変数操作の変換
  20. 20. VM言語への変換 ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  21. 21. 配列操作 メモリ上では、配列用に2種類のセグメントが設けられる ・ 配列の全ての要素を格納するセグメント ・ 最初の要素が入ったアドレス(ベースアドレス)を格納するセグメント
  22. 22. 配列操作 例 4 6 2 ・・・ 4315 メモリ (RAM) 配列の全要素を格納 bar 43 15 43 16 43 17 ベースアドレスを格納
  23. 23. 配列操作 bar[2] を別の値 8 に置き換えるスタック操作は?
  24. 24. 配列操作 bar[2] を別の値 8 に置き換えるスタック操作は? ①. 変更したい要素が格納されているアドレスを取得 ②. pointer 1 というアドレスに ①のアドレスを入れる ③. that というアドレスに変更後の値を入れる
  25. 25. 配列操作 ①. 変更したい要素が格納されてるアドレスを取得 → bar[2]のアドレス bar+2 を取得 4 6 2 ・・・ 4315 RAM bar 4 315 4 316 4 317 bar +2
  26. 26. 配列操作 ②. pointer 1 というアドレスに ① のアドレスを入れる 4 6 2 ・・・ 4315 RAM bar 4 315 4 316 4 317 bar + 2 pointer 1
  27. 27. 配列操作 ③. that というアドレスに変更後の値を入れる 4 6 2 ・・・ 4315 bar 4 315 4 316 4 317 bar + 2 pointer 1 8 that
  28. 28. 配列操作 thatセグメント は、特別な振る舞いをする! ・pointer 1 に格納されているアドレスを参照 ・そのアドレスにアクセスし、データを変更 ⇒ bar + 2 アドレスを参照し、 bar + 2 アドレスのデータを8に変更 4 6 2 ・・・ 4315 bar 4 315 4 316 4 317 bar + 2 pointer 1 8that
  29. 29. 配列操作 ①. 変更したい要素が格納されているアドレスを取得 ②. pointer 1 というアドレスに ① のアドレスを入れる ③. that 0 というアドレスに変更後の値を入れる bar[2] = 8 ※ bar を、local 2 としている ① ② ③
  30. 30. VM言語への変換 ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  31. 31. オブジェクト操作 オブジェクト操作は大きく分けると2種類 ・ データ操作 ・ メソッド操作
  32. 32. オブジェクト操作(データ編) オブジェクトのデータ → field変数 データ操作 ・コンパイラは、適当な空いているセグメントにfield変数を入れる ・どのセグメントを使っているかを認識するため、ベースアドレスを 作っておく
  33. 33. オブジェクト操作(データ編) ・コンパイラは、適当な空いているセグメントにfield変数を入れる ・どのセグメントを使っているかを認識するため、ベースアドレスを 作っておく → 配列と似ている! field2 field3 field1 ・・・ 4315 メモリ (RAM) 全fieldを格納 hoge (オブジェクト名) 43 15 43 16 43 17 ベースアドレスを格納
  34. 34. オブジェクト操作(データ編) hogeオブジェクトの2番目のフィールドを hoge.f2 = 5 とするための操作は? 1. pointer 0 にオブジェクトのベースアドレス を格納 1. thisセグメントに変更後の値を格納 4 6 2 ・・・ 4315 hoge 4 315 4 316 4 317 hoge pointer 0 5this f1 f2 f3
  35. 35. オブジェクト操作(データ編) ・thisセグメントは、pointer0に格納されてるアドレス にアクセス (オブジェクトにアクセス) ・this 1 で2番目のfieldにアクセス 4 6 2 ・・・ 4315 hoge 4 315 4 316 4 317 hoge pointer 0 5this f1 f2 f3
  36. 36. オブジェクト操作(データ編) hoge.f2 = 5 ※argument 0 は、hogeを表す 4 6 2 ・・・ 4315 hoge 4 315 4 316 4 317 hoge pointer 0 5this f1 f2 f3
  37. 37. オブジェクト操作(メソッド編) コンパイラは b.mult(5) に対して、multメソッドはbオブジェクトのものと認識する必要あり! → メソッドの第一引数には、オブジェクトを入れるルールにする! mult(b, 5)
  38. 38. オブジェクト操作(メソッド編) b.mult(5) → mult(b, 5) →
  39. 39. オブジェクト操作(メソッド編) どのオブジェクトのメソッドか認識する → メソッドの第一引数には、オブジェクトを入れるルールにする! → メソッドのシンボルテーブル(p.265参照)では、 オブジェクトが登録されている!
  40. 40. VM言語への変換 ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  41. 41. 式の評価 次のプロセスで、式評価のVMコードが生成される 式 構文木 VMコード + x * g 5 2 y - z
  42. 42. 式の評価 スタックベースのプラットフォームでは、 逆ポーランド記法を使ってVMコードを生成! 逆ポーランド記法 式を被演算子、演算子の順に書く記法 例 x+y → x, y, + x ー y * z → x, y, z, *, ー
  43. 43. 式の評価 逆ポーランド記法を使って、VMコード生成する例 ① x+y → x, y, + → ② x ー y * z → x, y, z, *, ー →
  44. 44. VM言語への変換 ・ 変数操作 ・ 配列操作 ・ オブジェクト操作 ・ 式の評価 ・ フロー制御
  45. 45. フロー制御 if 文と while 文 の VMコードを見る ・if 文 ・while文
  46. 46. コンパイラの仕様 教科書p.261 ~ 263 参照
  47. 47. 実装
  48. 48. 実装例 5つのモジュールを作成 ・JackCompiler ・JackTokenizer ・SymbolTable ・VMWriter ・CompilationEngine 今回の実装
  49. 49. テストの手順 準備 : 自作コンパイラ、projects/11にあるテスト用ファイル、 tools/OSにある全ての vmファイル、 VMエミュレータ 手順 (1. 任意の場所にテスト用ディレクトリを作成) 2. テスト用ディレクトリ内にテスト用ファイルとvmファイルを全て入れ る 3. 自作コンパイラでコンパイル 4. VMエミュレータで動作確認
  50. 50. サンプルのVMコード ・ 教科書p.265 の図 ・ tools ディレクトリに JackCompiler があるので、それでテスト用プ ロ グラムをコンパイル → 同じディレクトリにvmファイルが作成される
  51. 51. Appendix
  52. 52. 配列用セグメントの生成タイミング 配列で使われるセグメント ・ベースアドレス用 ・全要素用 → 2つは割り当てられる タイミングが違う! 4 6 2 ・・・ 4315 メモリ (RAM) 配列の全要素を格納 bar 43 15 43 16 43 17 ベースアドレスを格納
  53. 53. 配列用セグメントの生成タイミング ・ベースアドレス用 定義 ( 初期化 ) されるタイミング var int[] bar; ・全要素用 new でオブジェクトが生成されるタイミング bar = Array.new(3);

×