言語理論とコンパイラ

第十三回: 意味解析、コード生成

2015 年 7 月 3 日

http://www.sw.it.aoyama.ac.jp/2015/Compiler/lecture13.html

Martin J. Dürst

AGU

© 2005-15 Martin J. Dürst 青山学院大学

目次

 

前回のまとめ

 

 

これからの予定

 

過去問とその活用方法

 

過去問活用方法

 

コンパイラの主な段階

 

意味解析

(semantic analysis)

 

型の等価

(type equivalence)

型が同じかどうか複数の定義がある:

C の例: type-equivalence.c (コンパイル可能か)

 

型の等価: Haskell の例

 

コード生成と最適化の関係

 

コード生成の手法

 

コード生成の難しさ

機械によって使える命令が大幅に違う

 

機械の主な種類

 

コードの書き方: アセンブリ言語

(assembly language)

 

超単純アセンブリ言語

命令の種類
命令 被演算子 説明 (コメント)
LOAD R1, a メモリの変数 a の値をレジスタ R1 に代入
STORE a, R1 レジスタ R1 の値をメモリの変数 a に代入
CONST R1, 5 レジスタ R1 に 5 の定数を代入
JUMP label 無条件に label へジャンプ
JUMP< R1, label レジスタ R1 が 0 より小さい時 label へジャンプ (JUMP>=, JUMP!= などは同様)
ADD R1, R2, R3 R2 と R3 を足して R1 に代入。同じレジスタを何回使ってもよい。同様に SUB、MUL、DIV がある。

 

構文木からのコード生成

 

超単純アセンブリ言語の一例

入力のプログラムの一部:

sum += price * 25;

出力:

LOAD   R1, price    ; R1 (レジスタ1) に price というアドレスからロード
CONST R2, 25 ; R2 (レジスタ2) に 25 の定数をロード
MUL R1, R1, R2 ; R1 に R1 と R2 の掛け算の結果を入れる
LOAD R2, sum ; R2 に sum というアドレスからロード
ADD R2, R1, R2 ; R2 に R1 と R2 の合計を入れる
STORE sum, R2 ; sum というアドレスに R2 を入れる

 

if 文などのコード生成

 

if 文のコード生成の例

元の文: if (a>10) b = 15;

生成されるコード:

       LOAD    R1, a
CONST R2, 10
SUB R3, R1, R2 ; R3 = a-10
JUMP<= R3, endif ; jump over 'if' part if a-10<=0
CONST R4, 15
STORE b, R4
endif:

 

制限された C 言語

(人間のための) 中間表現

 

制限された C 言語の例

元の文:
if (a>10) b = 15;

条件を 0 との比較にする:

if (a-10>0) b = 15;

ラベルの追加:

  if (a-10>0)
b = 15;
endif:

条件の反転と goto の導入:

  if (a-10<=0)
goto endif;
b = 15;
endif:

 

ifelse 文のコード生成の例

C のプログラム

if (a > b)
c = a;
else
c = b;

プログラムの変更

  if (a-b <= 0)
goto else;
c = a;
goto end;
else:
c = b;
end:

 

ifelse 文のコード生成の結果

       LOAD   R1, a
LOAD R2, b
SUB R1, R1, R2 ; a-b > 0
JUMP<= R1, else
LOAD R1, a
STORE c, R1
JUMP end
else: LOAD R1, b
STORE c, R1
end:

 

論理和のコード生成

if (a>10 || b < 3)
c = 5;

コードの変更:

if (a>10)
c = 5;
else if (b < 3)
c = 5;

 

論理和のコード再生の結果

       LOAD   R1, a
CONST R2, 10
SUB R1, R1, R2 ; a-10 > 0
JUMP<= R1, else
CONST R1, 5
STORE c, R1
JUMP end
else: LOAD R1, b
CONST R2, 3
SUB R1, R1, R2 ; b-3 < 0
JUMP>= R1, end
CONST R1, 5
STORE c, R1
end:

 

while 文のコード生成

C 言語

while (a < 20)
a += 3;

制限された C 言語

next:  if (a-20 >= 0) goto break;
a += 3;
goto next;
break:

 

while 文のコード生成の結果

next:  LOAD   R1, a
CONST R2, 20
SUB R1, R1, R2
JUMP>= R1, break
LOAD R1, a
CONST R2, 3
ADD R1, R1, R2
STORE a, R1
JUMP next
break:

 

宿題

提出期限と場所: 2015年7月9日 (木) 19:00 まで O棟5階の O-529 号室の前の箱に投入

形式: A4 一枚、表紙なし

課題 1: 論理積のコード生成: C 言語の断片
if (c<3 && d>=15) a=b;
を「制限された C 言語」と「超単純アセンブリ言語」に変換しなさい。

課題 2 (発展問題): for 文のコード生成: C 言語の断片
for (i=0; i<20; i++) x*=y;
を「制限された C言語」と「超単純アセンブリ言語」に変換しなさい。

ヒント (両課題共通: 最初に C 言語の変換で問題の部分をなくす (例: forwhile に変換))