Cpu0のバックエンドをLLVMに追加するプロジェクト、9章の後半では、関数コールの様々な方法についてみてみる。
今回も非常にファイル量が多くて、とりあえずLLVMをビルドするためだけにパッチを作って当てているが、LLVM 7.0は未サポートになっている部分が多く、ソースコードを書き直す必要があった。
そろそろチュートリアルを読んだだけでは訳が分からなくなってきたので、自分で手を動かしてRISC-Vのバックエンドを追加できるように頑張ってみたい。
Cpu0のバックエンドをLLVMに追加するプロジェクト、9章の後半では、さまざまな形の関数コールをサポートする。
今回も非常にファイル量が多くて、とりあえずLLVMをビルドするためだけにパッチを作って当てているが、LLVM 7.0は未サポートになっている部分が多く、ソースコードを書き直す必要があった。
構造体のサポート
初期の構造体のサポート
関数コール内での構造体のサポートを行う。
def RetCC_Cpu0EABI : CallingConv<[ // i32 are returned in registers V0, V1, A0, A1 CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>> ]>;
構造体の帰り値は帰り値が4つのレジスタを超えない場合、V0, V1, A0, A1に格納する。 もし次の4つのレジスタを超える倍、Cpu0は値をメモリに格納して、レジスタにはそのポインタの場所を格納する。
byval構造体
関数コールの最適化
末尾再帰の最適化(Tail call optimization)
幾つかの状況では、関数の呼び出し元と呼び出し先は同じメモリスタックを共有する。この場合再帰的な関数呼び出しでは、漸近的にスタックの必要量が線形になるか、O(n)か定数かO(1)になる。LLVM IRは末尾呼び出しをサポートする。
lbdex/input/ch9_2_tailcall.cpp
int factorial(int x) { if (x > 0) return x*factorial(x-1); else return 1; } int test_tailcall(int a) { return factorial(a); }
$ ./bin/clang -target mips-unknown-linux-gnu -c ../lbdex/input/ch9_2_tailcall.cpp -emit-llvm -o ch9_2_tailcall.bc $ ./bin/llvm-dis ch9_2_tailcall.bc -o - define dso_local i32 @_Z9factoriali(i32 signext %x) #0 { entry: %retval = alloca i32, align 4 %x.addr = alloca i32, align 4 store i32 %x, i32* %x.addr, align 4 %0 = load i32, i32* %x.addr, align 4 %cmp = icmp sgt i32 %0, 0 br i1 %cmp, label %if.then, label %if.else if.then: ; preds = %entry %1 = load i32, i32* %x.addr, align 4 %2 = load i32, i32* %x.addr, align 4 %sub = sub nsw i32 %2, 1 %call = call i32 @_Z9factoriali(i32 signext %sub) %mul = mul nsw i32 %1, %call store i32 %mul, i32* %retval, align 4 br label %return if.else: ; preds = %entry store i32 1, i32* %retval, align 4 br label %return return: ; preds = %if.else, %if.then %3 = load i32, i32* %retval, align 4 ret i32 %3 }
再帰の最適化
他の機能のサポート
このセクションでは、
- PICアドレッシングモードの場合の$gpレジスタの呼び出し元保存
- jsub命令では24ビットのアドレス範囲のみをサポートしている。これをjalrにより32ビットのアドレス範囲まで拡張した。これには、Cpu0が1命令で32ビットのアドレッシングを可能にさせるためにある。そしてjalrをPICモードの動的リンク関数にも使用する。
- 可変長引数のサポート
- 動的なスタックの割り当て
をサポートする。