単子葉類プログラマーのメモ

プログラミング関連の自分用メモだけど他の人の役に立つかもしれないので公開しておく感じのブログ

LLVM C++ API 学習メモ(6) - Constantの中身を取り出す方法

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_castValue*型の値を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();
}