【问题标题】:LLVM insert pthread function calls into IRLLVM 将 pthread 函数调用插入 IR
【发布时间】:2013-11-06 03:59:42
【问题描述】:

我正在编写一个 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*,它允许我将新的函数调用 printf 插入 IR。

我的通行证中有#include "pthread.h"-pthread 就在clang -emit-llvm 之后,但它仍然找不到pthread_create 或其他pthread_* 函数。

【问题讨论】:

    标签: linker pthreads llvm llvm-ir


    【解决方案1】:

    当您拨打电话时:

    currentModule->getFunction("pthread_create");
    

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

    相反,您想要求 LLVM 获取或插入您需要的函数。通过插入,我们的意思是为函数添加一个声明。此调用需要插入函数的完整类型信息。由于我碰巧有一些基本上为 pthread_create 执行此操作的代码,因此我在此处复制了一个 sn-p 并将进一步解释:

    // 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*。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 编译一个 C 程序,看看 IR 帮助很大!谢谢!
      猜你喜欢
      • 2014-12-28
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多