LLVM将pthread函数调用插入IR中

4
我正在编写一个LLVM pass(它是一个LoopPass),需要在IR中插入pthread函数调用,如pthread_create()和pthread_join()。我知道如何创建和插入函数调用到IR中,但是我无法获取LLVM中Function*的pthread表示形式。
这是我拥有的: Function *pthread_create_func = currentModule->getFunction("pthread_create"); 但是它返回NULL。
相比之下,Function *printf_func = currentModule->getFunction("printf");将返回正确的Function*,允许我将新的函数调用插入到IR中。
我在我的pass中包含了#include "pthread.h",并在clang -emit-llvm之后立即添加了-pthread,但它仍然无法找到pthread_create或其他pthread_*函数。
2个回答

8

当你发起调用时:

currentModule->getFunction("pthread_create");

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

相反,你需要要求LLVM获取或插入所需的函数。插入意味着添加一个函数声明。此调用需要被插入函数的完整类型信息。因为我恰好有一些基本上是为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*,并将其视为void*,但这可能对你不起作用。
第三,funVoidPtrVoidTy是一个FunctionType,代表pthread_create的start_routine。
第四,最后一个参数实际上是一个void指针,是传递给start_routine的未知参数。
将四个参数类型放入数组中,创建一个函数类型。简要地说,我们请求一个返回32位整数(int32Ty)的函数类型,并将四个类型作为参数(ArrayRef...),最后不接受varg类型(false)。
最后,我们可以请求模块添加我们想要的函数声明,然后使用我们创建的IR中的Function*。

5

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


编译一个C程序并查看IR非常有帮助!谢谢! - user2958862

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