使用LLVM C API生成对内在的调用

时间:2014-12-28 23:01:54

标签: llvm intrinsics

我正在处理一些使用LLVM C API的代码。如何使用内在函数,例如llvm.cos.f64llvm.sadd.with.overflow.i32?每当我尝试通过生成带LLVMAddGlobal的全局(具有正确的类型签名)来实现它时,我只是在JIT链接阶段得到此错误消息:

LLVM ERROR: Could not resolve external global address: llvm.cos.f64

我没有使用LLVM C ++接口,因此LLVM insert intrinsic function Cos中的建议似乎不适用。

我认为我需要像Intrinsic::getDeclaration这样的东西,但我似乎无法找到它。我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:3)

无需离开C API。将内在名称传递给LLVMAddFunction

LLVMTypeRef param_types[] = {LLVMDoubleType()};
LLVMTypeRef fn_type = LLVMFunctionType(LLVMDoubleType(), param_types, 1, false);
LLVMValueRef fn = LLVMAddFunction(module, "llvm.cos.f64", fn_type);

然后,您可以使用fn生成对LLVMBuildCall的来电。

答案 1 :(得分:1)

我现在已经通过编写一小段C ++代码解决了这个问题,该代码调用了我在另一个问题llvm::Intrinsic::getDeclaration中引用的API,并且我使用了一些魔法来获取合法内在函数列表。我宁愿用一个纯粹的C API完成这个,但是我需要让事情有效,这比我对严格语言纯度的要求更强。


要获取内在函数的名称列表,我这样做:

static const char *const intrinsicNames[] = {
#define GET_INTRINSIC_NAME_TABLE
#include "llvm/IR/Intrinsics.gen"
#undef GET_INTRINSIC_NAME_TABLE
};

这会生成一个已排序的表,因此我可以使用bsearch来查找我想要的ID。

static int search(const void *p1, const void *p2) {
  const char *s1 = (const char *) p1;
  const char *s2 = *(const char **) p2;
  return strcmp(s1, s2);
}
int GetLLVMIntrinsicIDFromString(const char* str, llvm::Intrinsic::ID& id) {
  void *ptr = bsearch(str, (const void *) intrinsicNames,
    sizeof(intrinsicNames)/sizeof(const char *),
    sizeof(const char *), search);
  if (ptr == NULL)
    return 0;
  id = (llvm::Intrinsic::ID)((((const char**) ptr) - intrinsicNames) + 1);
  return 1;
}

为了得到我可以调用的实际内在函数,我这样做(需要模块引用和参数类型引用):

// Omitting exactly how I obtain these values but the types are mostly LLVM C API types.
// The only one that was awkward was the ID which was cast from an offset into that table above.
LLVMModuleRef mod = ...;
llvm::Intrinsic::ID = ...;
LLVMTypeRef ty = ...;

std::vector<llvm::Type *> arg_types;
arg_types.push_back(llvm::unwrap(ty));

LLVMValueRef rt = llvm::wrap(llvm::Intrinsic::getDeclaration(llvm::unwrap(mod), id, arg_types));

LLVMValueRef适用于LLVM C API的其余部分。关键是我正在使用llvm::unwrapllvm::wrap