LLVM如何从Value*获取常量整数

32

我使用以下方式从整数常量创建一个llvm::Value*:

llvm::Value* constValue = llvm::ConstantInt::get( llvmContext , llvm::APInt( node->someInt() ));

现在我想要检索编译时常量的值;

int constIntValue = constValue->???

LLVM程序员手册中展示的例子似乎暗示着,当使用类型(而不是类型加指针)模板参数时,cast<>将接受一个指针,然而我相当确定这在2.8版本之后已经失效:

llvm::Value* foo = 0;
llvm::ConstantInt* intValue = & llvm::cast< llvm::ConstantInt , llvm::Value >(foo );

//build error:
//error: no matching function for call to ‘cast(llvm::Value*&)’

在这里什么是正确的方法?

3个回答

47

Eli的回答很好,但是缺少最后一步,那就是将整数取回。完整的步骤应该如下:

if (ConstantInt* CI = dyn_cast<ConstantInt>(Val)) {
  if (CI->getBitWidth() <= 32) {
    constIntValue = CI->getSExtValue();
  }
}
当然,如果constIntValue是一个64位整数等等,你也可以将其更改为<= 64
正如Eli所写的那样,如果您确信该值确实是 ConstInt 类型,您可以使用 cast<ConstantInt>而不是dyn_cast

39

假设你有一个llvm::Value* foo,并且你知道foo实际上是一个ConstantInt,我认为在LLVM代码中惯用的方法是使用dyn_cast,如下所示:

if (llvm::ConstantInt* CI = dyn_cast<llvm::ConstantInt>(foo)) {
  // foo indeed is a ConstantInt, we can use CI here
}
else {
  // foo was not actually a ConstantInt
}

如果你绝对确定foo是一个ConstantInt,并且准备好在它不是时遭受断言失败的打击,那么你可以使用cast而不是dyn_cast

注意,castdyn_cast是LLVM自己实现的RTTI的一部分。 dyn_cast在某种程度上类似于标准的C++ dynamic_cast,尽管在实现和性能方面存在差异(可以在这里了解)。


根据您提供的链接,如果指针没有指向预期类型,那么cast将导致断言失败,而dyn_cast则会返回0,而不是相反。 - RoastDuck
如何检测此ConstantInt是有符号还是无符号的? - linrongbin

2

如果常量变量是当前文件中的变量,则其他答案可以工作。

但是,如果常量变量是在其他文件中定义的全局变量,并且由当前文件通过extern引用。在这种情况下,当前文件中的变量是PointerType值。我们必须通过以下代码获取其真实值:

Constant *c;

if (isa<GlobalValue>(c)) {
        GlobalValue *gvalue = dyn_cast<GlobalValue>(c);
        GlobalVariable *gv = dyn_cast<GlobalVariable>(gvalue);
        ConstantInt *ci = dyn_cast<ConstantInt>(gv->getInitializer());
        errs() << ci->getValue();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接