3

LoopPasspthread_create() や pthread_join() などの pthread 関数呼び出しを IR に挿入する必要がある LLVM パス ( ) を作成しています。関数呼び出しを作成して 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_createpthread_*

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 ビット マシンかによってサイズが異なります。したがって、正しい型シグネチャを使用するには、これを考慮する必要があります (または、 1 つのアーキテクチャ)。

第二に、私の目的のために、解決を回避%union.pthread_attr_t*し、それをvoid*として扱うことができましたが、それはあなたにとってはうまくいかないかもしれません.

3 番目に、funVoidPtrVoidTy は、pthread_create への start_routine を表す FunctionType でした。

第 4 に、最後の引数は実際には void ポインターであり、start_routine に渡される未知の引数です。

配列内の 4 つの引数型を使用して、関数型が作成されます。簡単に言うと、32 ビット整数を返し ( int32Ty)、4 つの型を引数として取り ( ArrayRef...)、最終的に可変長型を取り込まない( ) 関数の型を要求しましたfalse

最後に、必要な関数の宣言を追加するようにモジュールに要求できます。その後、作成した IR で Function* を使用します。

于 2013-11-06T15:52:21.337 に答える
5

pthread_createIRで関数の宣言が必要です。printfLLVMがビルトインとして認識するため、機能しprintfます。pthread_createwithを使用する単純な C プログラムをコンパイルclang -emit-llvmし、生成された IR を確認することをお勧めします。

于 2013-11-06T04:12:06.373 に答える