PRINT文の実装について。
10 PRINT A+1
みたいなPRINT (数式)という構文のみを実装する。
本当は文字列の表示にも対応させたいのだけど、文字変数とか文字定数を実装しないといけないので、結構な手間になる。
手抜きの為に、数式のみ実装することにした。
まず、出力コードの先頭に次の2行のLLVM-IRのコードを前もって出力しておく。
@.1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 declare i32 @printf(i8*, ...) nounwind
1行目は、文字列の定数の定義だ。4バイトの配列で、C言語表記で”%d\0A\00″という内容となる。
2行目が、外部の関数の定義で、C言語のprintfを呼び出すための定義だ。
そして、PRINT文のコード生成をする。
まず数式の、例えば A+1 などを前に書いていたようにコード生成して、
使い捨てのレジスタ的な変数 %1に入れる。 (%1でなくて、もっと数字が進んでいる場合もある)
そして、
%2 = call i32(i8*,...)* @printf(i8* getelementptr inbounds([4 x i8]* @.1, i32 0, i32 0), i32 %1) nounwind
と、いうコードで外部のprintf関数を呼び出す。
C言語で printf(“%d\n”,変数);のコード生成したのと大体同じコードだ。
外部のprintf関数のライブラリはllvm-asなどでLLVM-IR中間コードをビルドしてリンケージエディタでリンクをするときに自動でリンクされる。
これでPRINT文が実装できた。
文字列を表示できないと不便なので、
PRINTX “文字列”という構文も用意した。
文字変数には対応しないでここだけ使える文字定数のような仕組みで実現される。
PRINTXの”文字列”をストックしておいて、PRINTX文のコード生成のたびに
printf(“%s\n”,%変数);みたいなコード出力をして、
LLVM-IRソースコード出力の最後にまとめて文字定数を全部出力する。
ちょっと手抜きだが、PRINT文と文字列の表示の実装ができた。