LLVM insert pthread function calls into IR

↘锁芯ラ 提交于 2019-12-19 04:12:25

问题


I'm writing a LLVM pass (it's a LoopPass) that needs to insert pthread functions calls like pthread_create() and pthread_join() into the IR. I know how to create and insert a function call into IR, but I am having trouble to get the pthread representation of Function* in LLVM.

Here's what I have:

Function *pthread_create_func = currentModule->getFunction("pthread_create"); but it returns NULL.

As a comparison Function *printf_func = currentModule->getFunction("printf"); will return the correct Function* that allows me to insert a new function call to printf into IR.

I have #include "pthread.h" in my pass and -pthread right after clang -emit-llvm but it still can't find pthread_create or other pthread_* functions somehow.


回答1:


When you make the call:

currentModule->getFunction("pthread_create");

LLVM looks up to see if there already is a function declaration with this name. The return of NULL indicates that the existing IR did not declare this function, which contrasts with printf that has been declared.

Instead, you want to ask LLVM to get or insert the function you need. By insert, we mean add a declaration for the function. This call requires the complete type information for the function being inserted. As I happen to have some code that basically does this for pthread_create, I've copied a snippet here and will explain further:

// The following are Type*: int64Ty, int32Ty, pthreadTy
// Request the types using context, like int32Ty = Type::getInt32Ty(M.getContext());
// funVoidPtrVoidTy is a FunctionType*, constructed in a similar manner as below
if (M.getPointerSize() == llvm::Module::Pointer64)
{
    pthreadTy = int64Ty;
}
else
{
    pthreadTy = int32Ty;
}

Type* argsPTC[] = {pthreadTy->getPointerTo(),
                   voidPtrTy,
                   static_cast<Type *>(funVoidPtrVoidTy)->getPointerTo(),
                   voidPtrTy};
FunctionType* pthreadCreateTy = FunctionType::get(int32Ty, 
                                                  ArrayRef<Type*>(argsPTC,4), 
                                                  false);
Function *pthread_create_func = M.getOrInsertFunction("pthread_create",
                                                      pthreadCreateTy);

pthread_create has the following type signature:

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, \
                   void * (*start_routine)(void *), void * arg)

To insert this function, we need to assemble a list of the type of the arguments.

First, the pthread_t type varies in size, depending on whether you are on a 32- or 64-bit machine, therefore to have the correct type signature needs to take this into account (or you can hardcode it, if you are only concerned with one architecture).

Second, for my purposes, I was able to avoid resolving %union.pthread_attr_t*, and treat it as a void*, but that may not work for you.

Third, funVoidPtrVoidTy was a FunctionType that represents the start_routine to pthread_create.

Fourth, the last argument is actually a void pointer, being the unknown argument passed to the start_routine.

With the four argument types in an array, a function type is created. Briefly, we've requested the type of a function that returns a 32-bit integer (int32Ty) and takes in the four types as arguments (ArrayRef...), and finally does not take in a varg type (false).

At last, we can request the module to add a declaration for the function we want, and away we go using the Function* in IR we create.




回答2:


You need a declaration of the pthread_create function in your IR. It works for printf because LLVM recognizes printf as a builtin. I suggest you compile a simple C program that uses pthread_create with clang -emit-llvm and look at the produced IR.



来源:https://stackoverflow.com/questions/19803848/llvm-insert-pthread-function-calls-into-ir

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!