Generate a call for internal use of the LLVM C API

I am working on some code that uses the LLVM C API. How to use built-in functions like llvm.cos.f64or llvm.sadd.with.overflow.i32? Whenever I try to do this by creating a global using LLVMAddGlobal(with the correct type signature), I just get this error message during the JIT build phase:

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

I do not use the LLVM C ++ interface, so the tip in LLVM inserts the Cos internal function , it does not seem to apply.

I guess I need something like Intrinsic::getDeclaration, but I can not find it. Am I missing something?

+4
source share
2 answers

Now I solved this by writing a short piece of C ++ code that calls the API that I referenced in another question llvm::Intrinsic::getDeclaration, and I use a bit of magic to get a list of legal properties. I would rather do this with a pure C API, but my need to do something is stronger than my need for a strict clean language.


To get a list of intrinsics names, I do this:

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

This creates a sorted table, so I can use the bsearchidentifier I want to search.

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;
}

To get the actual internal value that I can call, I do this (which requires a module reference and an argument type reference):

// 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::unwrap llvm::wrap.

+1

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

Source: https://habr.com/ru/post/1569238/


All Articles