配列変数の実装について、書くのを忘れていた。
10 DIM A(10)
みたいにTinyBasicで配列宣言をしたときに、LLVM-IRでそれに対応したコードを生成する。
通常の変数の場合は、最初に出現した時に生成するのだが、配列はDIM文で宣言が必要という仕様だ。
%_A0 = alloca [11 x i32], align 4
というように11個の32bit整数のメモリ空間を割り当てる。
10個で無いのは、A(0)~A(10)まで11個だからだ。
20 A(1)=2
のような代入文は、
store i32 1 , i32* %acc, align 4 %1 = load i32* %acc, align 4 store i32 2 , i32* %acc, align 4 %2 = load i32* %acc, align 4 %3 = getelementptr inbounds [11 x i32]* %_A0, i32 0, i32 %1 store i32 %2, i32 * %3, align 4
と、このようにgetelementptrを使う。
30 PRINT A(1)+A(2)+A(3)
の場合は、
store i32 1 , i32* %acc, align 4 %10 = load i32* %acc, align 4 %11 = getelementptr inbounds [11 x i32]* %_A0, i32 0, i32 %10 %12 = load i32* %11, align 4 store i32 %12, i32* %acc %13 = load i32* %acc, align 4 store i32 2 , i32* %acc, align 4 %14 = load i32* %acc, align 4 %15 = getelementptr inbounds [11 x i32]* %_A0, i32 0, i32 %14 %16 = load i32* %15, align 4 store i32 %16, i32* %acc %17 = load i32* %acc, align 4 %18 = add nsw i32 %13, %17 store i32 %18, i32* %acc %19 = load i32* %acc, align 4 store i32 3 , i32* %acc, align 4 %20 = load i32* %acc, align 4 %21 = getelementptr inbounds [11 x i32]* %_A0, i32 0, i32 %20 %22 = load i32* %21, align 4 store i32 %22, i32* %acc %23 = load i32* %acc, align 4 %24 = add nsw i32 %19, %23 store i32 %24, i32* %acc %25 = load i32* %acc, align 4 %26 = call i32(i8*,...)* @printf(i8* getelementptr inbounds([4 x i8]* @.1, i32 0, i32 0), i32 %25) nounwind
となる。
これでもう一通りTinyBasicコンパイラのコード生成の中身の解説は終了してしまったかな。