LLVMにはすでにRISC-Vのバックエンドサポートが追加されている。しかし、勉強のために独自のRISC-V実装をLLVMに追加している。
第6章はグローバル変数をサポート。 グローバル変数のサポートには4種類があって、それぞれどのような処理が必要なのか見ていく。
- リロケーションモード : static, Smallsection : 未使用
- リロケーションモード : static, Smallsection : 使用
- リロケーションモード : PIC, Smallsection : 未使用
- リロケーションモード : PIC, Smallsection : 使用
グローバル変数
これまではローカル変数についてみてきたが、今回はグローバル変数のアクセス変換について学ぶ。
グローバル変数のDAG変換は、過去に学んだDAG変換とは異なる。
バックエンドのC++コードが、llc -relocation-moel
オプションに基づいてIR DAGノードを作成する。
一方で、他のDAGはIR DAGを直接マシンコードのDAGに変換する。
マシンコードのIR DAGはIR DAGの入力ファイルに基づく(例外的に、 Chapter3_4で使用するRetLR疑似命令は除く)。加えて、バックエンドを持っている場合は、アセンブリディレクティブ(マクロ)に関連するグローバル変数のための関数を出力するためのマシン命令について考えておく必要がある。
Chapter6_1
はグローバル変数をサポートしている。ch6_1.cpp
をコンパイルしてみよう。
リロケーションモード : static, Smallsection使用
- ch6_1.static.small.s
ori x10, x3, %gp_rel(gI) lw x10, 0(x10) sw x10, 4(x2) lw x10, 4(x2) ... .type gI,@object # @gI .globl gI .p2align 2 gI: .4byte 100 # 0x64 .size gI, 4
あれ?x3はどこから来たんだ?なんか問題がありそうな気がする。
ch6_1.static.large.s
lui x10, %hi(gI) ori x10, x10, %lo(gI) lw x10, 0(x10) sw x10, 4(x2) lw x10, 4(x2) ... .type gI,@object # @gI .globl gI .p2align 2 gI: .4byte 100 # 0x64 .size gI, 4
こちらはSmallsectionを使わないので、アドレスを2命令を使って生成している。
ch6_1.pic.small.s
lw x10, %got(gI)(x3) lw x10, 0(x10) sw x10, 4(x2) lw x10, 4(x2)
こちらはGOTを使って生成する。そしてSmallsectionなのでアドレス生成も1命令で。
ch6_1.pic.large.s
lui x10, %got_hi(gI) add x10, x10, x3 lw x10, %got_lo(gI)(x10) lw x10, 0(x10) sw x10, 4(x2) lw x10, 4(x2)
こちらはGOTを使って、さらにアドレスを2命令で生成している。