3

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

这是我所拥有的:

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

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

#include "pthread.h"在我的通行证和-pthread之后,clang -emit-llvm但它仍然无法以某种方式找到pthread_create或其他pthread_*功能。

4

2 回答 2

7

当您拨打电话时:

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*,并将其视为无效*,但这可能对您不起作用。

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

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

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

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

于 2013-11-06T15:52:21.337 回答
5

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

于 2013-11-06T04:12:06.373 回答