電話をかけるとき:
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* を使用します。