独自言語 picle のコンパイラ化(その3) [PIC]
PIC24FJ用の picle言語 のセルフコンパイラの製作をしばらく中断して作業が止まっていましたがゆっくりと再開します ^^;
また、picle の インタープリタ 開発の際は途中経過を色々記事に書きましたが、そのことにどれだけ意味があるのか?という疑問はあるもののブログの書込みがあまりにも滞るのもなんなので少し書いてみます。
当初は完全な 1パスコンパイラの想定(字句解析、構文解析、コード生成(リンクも含む)をまとめて行う)でしたが、 前回のその2 に書いたようにフラッシュメモリへの書込み回数削減のためにエラーチェック後、コンパイルしながらフラッシュメモリに書き込む方式にしています。コンパイル時のメモリ使用量を削減するために構文木も作成していません。(PIC24FJはフラッシュはそれなりに多いのですが、メモリサイズが小さいので使用量は最小限にしたいため)
実装を検討していくと色々な課題が見えてきました。
下記はIF文のコンパイル結果の例です。
まだフラッシュへの書き込みは行っておらず、アセンブルのニーモニック表示のみしている段階です。現時点では最適化していませんが、一通り完成後に最適化する予定です。
0x800a が test()処理 のエントリアドレスで 0x800e が IF文の開始アドレス、0x8030 が else 句の開始アドレス、0x8038 がIF文の終了直後のアドレスです。
因みに 0x8006 はどこからもコールされていませんが、exit() 処理のエントリ用のコードです。
IF文のコンパイル例
[TOP] [ 前へ ] 連載記事 [ 次へ ]
また、picle の インタープリタ 開発の際は途中経過を色々記事に書きましたが、そのことにどれだけ意味があるのか?という疑問はあるもののブログの書込みがあまりにも滞るのもなんなので少し書いてみます。
当初は完全な 1パスコンパイラの想定(字句解析、構文解析、コード生成(リンクも含む)をまとめて行う)でしたが、 前回のその2 に書いたようにフラッシュメモリへの書込み回数削減のためにエラーチェック後、コンパイルしながらフラッシュメモリに書き込む方式にしています。コンパイル時のメモリ使用量を削減するために構文木も作成していません。(PIC24FJはフラッシュはそれなりに多いのですが、メモリサイズが小さいので使用量は最小限にしたいため)
実装を検討していくと色々な課題が見えてきました。
- 課題:前方アドレスの参照
制御構文をマシン語化する場合、ジャンプ先として前方アドレスが必要となります。
例えば IF文で条件が false の場合、IF文の最後(または else 句)にジャンプする必要がでてきますが、完全な1パス処理では後方へのジャンプは(アドレスが既知なので)できても前方へのジャンプはアドレスが確定していないので処理できません。
メモリ上にマシン語コードを展開しているのであれば、ランダム書込みができるのでジャンプ先を後で書き換えられます(一種のリンク処理のようなもの)が、今回はフラッシュへ書きながらのコンパイルなのでシーケンシャル書込みが基本です。
- 解決方法
1パス目で制御構文で必要となるアドレスを一時保存して置き、2パス目で参照するようにしました。
実装的にはこの部分の処理では1パス/2パスの区別はなく、前方アドレスを保存領域から参照後に参照したかった実アドレスを保存領域に保存する処理にしています。2パス目では必然的に1パス目で保存したアドレスが参照できます。
実は1パス目では未設定なアドレスデータを参照(保存領域としてArray_領域を使用しているのでCコンパイラが初期化しない領域)することになり、Cコンパイラが未設定変数の参照で警告を出すかもしれないと思いましたが、ポインタでのアクセスのためかCコンパイラは気づかず warning は出ていません w
下記はIF文のコンパイル結果の例です。
まだフラッシュへの書き込みは行っておらず、アセンブルのニーモニック表示のみしている段階です。現時点では最適化していませんが、一通り完成後に最適化する予定です。
0x800a が test()処理 のエントリアドレスで 0x800e が IF文の開始アドレス、0x8030 が else 句の開始アドレス、0x8038 がIF文の終了直後のアドレスです。
因みに 0x8006 はどこからもコールされていませんが、exit() 処理のエントリ用のコードです。
:l 1:# if-else sentence test for picle self compiler (JIT type) 2: 3:proc test( x ) { 4: if ( x <> 1 ) { 5: PrnDec_( x ); 6: } else { 7: PrnDec_( 5 ); 8: } 9:} 10: 11: 12:proc main() { 13: test(7); 14:} :run 8000 : MOV W15,[ba0h] 8002 : MOV #b16h,W13 8004 : BRA 803ch 8006 : MOV [ba0h],W15 8008 : RETURN 800a : LNK #2 800c : MOV W0,[W14+0h] 800e : MOV [W14+0h],W0 8010 : MOV W0,[++W13] 8012 : MOV #1h,W0 8014 : MOV W0,[++W13] 8016 : MOV [W13--],W1 8018 : CP W1,[W13] 801a : CLR [W13] 801c : BRA Z,8020h 801e : INC [W13],[W13] 8020 : MOV [W13--],W0 8022 : CP0 W0 8024 : BRA Z,8030h 8026 : MOV [W14+0h],W0 8028 : MOV W0,[++W13] 802a : MOV [W13--],W0 802c : RCALL 178eh 802e : BRA 8038h 8030 : MOV #5h,W0 8032 : MOV W0,[++W13] 8034 : MOV [W13--],W0 8036 : RCALL 178eh 8038 : ULNK 803a : RETURN 803c : LNK #0 803e : MOV #7h,W0 8040 : MOV W0,[++W13] 8042 : MOV [W13--],W0 8044 : RCALL 800ah 8046 : ULNK 8048 : RETURN : |
[TOP] [ 前へ ] 連載記事 [ 次へ ]
コメント 0