LLVM C++ APIで数式の計算結果から定数の値を取り出す方法についてのメモ。
LLVMのバージョンは11.0.0。
目次
用途
独自の言語を作るとして、配列の宣言時のサイズ指定などで数式をサポートしたい場合がある。
例えば以下をコンパイルするコードを書く場合、llvm::ArrayType::get()
の第二引数に配列サイズとしてuint64_t
型の値を指定する必要がある。
int array[SOME_CONSTANT + 1]; // SOME_CONSTANTはマクロかconst定数
SOME_CONSTANT + 1
のような数式を自力で計算してuint64_t
値を作り出してもよいが、CreateAdd()
などの結果から定数を取り出すようにすれば、普通の数式の処理とコードを共通化できるので都合がよい。
CreateAdd()
などの戻り値はValue
型なのでそのままだと定数を取り出せないが、演算のもとになった値が両方とも定数なら、Constant
型にキャストしてそこから値を取り出すことができる。
Value
型をConstant
型にキャストする方法
llvmが提供しているdyn_cast
でValue*
型の値をConstant*
型にキャストできる。
定数でないものをキャストした場合はnullptr
が返される。
#include "llvm/Support/Casting.h" void someFunc(llvm::Value* value) { llvm::Constant* c = llvm::dyn_cast<llvm::Constant>(value); if (c != nullptr) { // c is constant } }
llvmはコンパイルオプションでランタイム型情報やC++例外を無効にしている。
llvmを利用する側も同じ設定にしなければならないため、C++標準のdynamic_cast
が使えない。
そのためllvmは独自のキャストdyn_cast
を提供していると思われる。
定数から値を取得する方法
Constant
の中身の値を取り出す方法は以下のとおり。
void getConstantInt(llvm::Constant* value) { llvm::APInt ap = value->getUniqueInteger(); // 符号ありで取得 int64_t result = ap.getSExtValue(); // 符号なしで取得 uint64_t result = ap.getZExtValue(); }