LLVM将pthread函数调用插入IR [英] LLVM insert pthread function calls into IR

查看:298
本文介绍了LLVM将pthread函数调用插入IR的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写LLVM传递(这是LoopPass),需要将pthread函数调用(例如pthread_create()和pthread_join())插入IR.我知道如何在IR中创建和插入函数调用,但是我在获取LLVM中Function*的pthread表示时遇到了麻烦.

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.

这就是我所拥有的:

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

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

作为比较,Function *printf_func = currentModule->getFunction("printf");将返回正确的Function*,这使我可以将对printf的新函数调用插入IR.

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.

我的通行证中有#include "pthread.h",紧随clang -emit-llvm之后是-pthread,但是仍然无法找到pthread_create或其他pthread_*函数.

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.

推荐答案

拨打电话时:

currentModule->getFunction("pthread_create");

LLVM查找是否已经存在具有该名称的函数声明.返回NULL表示现有IR未声明此功能,这与已声明的printf相反.

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.

相反,您想让LLVM获取或插入所需的功能.通过插入,我们的意思是为函数添加一个声明.此调用需要插入功能的完整类型信息.当我碰巧有一些代码基本上针对pthread_create进行此操作时,我在此处复制了一个代码段,并将进一步说明:

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

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.

首先,pthread_t类型的大小会有所不同,具体取决于您使用的是32位还是64位计算机,因此要获得正确的类型签名,必须考虑到这一点(或者,如果您使用的是硬编码,则可以对其进行硬编码)只关注一种架构).

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).

第二,出于我的目的,我能够避免解析%union.pthread_attr_t*并将其视为void *,但这可能对您不起作用.

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.

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

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

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

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

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

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).

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

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.

这篇关于LLVM将pthread函数调用插入IR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆