LLVM将pthread函数调用插入IR

时间:2013-11-06 03:59:43

标签: linker pthreads llvm llvm-ir

我正在写一个LLVM传递(它是LoopPass),需要将pthread函数调用(如pthread_create()和pthread_join()插入到IR中。我知道如何在IR中创建函数调用并插入函数调用,但是我无法在LLVM中获得Function*的pthread表示。

这就是我所拥有的:

Function *pthread_create_func = currentModule->getFunction("pthread_create"); 但它返回NULL。

作为比较Function *printf_func = currentModule->getFunction("printf");将返回正确的Function*,允许我向print中插入对printf的新函数调用。

我的传递中#include "pthread.h"-pthread之后clang -emit-llvm,但它仍然无法以某种方式找到pthread_create或其他pthread_*函数。

2 个答案:

答案 0 :(得分:6)

拨打电话时:

currentModule->getFunction("pthread_create");

LLVM查找是否已存在具有此名称的函数声明。返回NULL表示现有IR没有声明此函数,这与已声明的printf形成对比。

相反,您希望让LLVM获取或插入您需要的功能。通过insert,我们的意思是为函数添加一个声明。此调用需要插入函数的完整类型信息。因为我碰巧有一些代码基本上为pthread_create做了这个,所以我在这里复制了一个片段,并将进一步解释:

// 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具有以下类型签名:

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

要插入此函数,我们需要汇编参数类型的列表。

首先,pthread_t类型的大小会有所不同,具体取决于您使用的是32位还是64位计算机,因此需要将正确的类型签名考虑在内(或者您可以对其进行硬编码,如果您是只涉及一种架构。)

其次,就我的目的而言,我能够避免解析%union.pthread_attr_t*,并将其视为无效*,但这可能对您不起作用。

第三,funVoidPtrVoidTy是一个FunctionType,表示pthread_create的start_routine。

第四,最后一个参数实际上是一个void指针,是传递给start_routine的未知参数。

使用数组中的四个参数类型,将创建一个函数类型。简而言之,我们已经请求了一个函数的类型,该函数返回一个32位整数(int32Ty)并将四种类型作为参数(ArrayRef...)接受,最后不接受一个varg类型(false)。

最后,我们可以请求模块为我们想要的函数添加声明,然后我们使用我们创建的IR中的Function *。

答案 1 :(得分:5)

您需要在IR中使用pthread_create函数的声明。它适用于printf,因为LLVM将printf识别为内置。我建议你编译一个使用pthread_createclang -emit-llvm的简单C程序,然后查看生成的IR。