creating and inserting a function with variable arguments

I am working on a pass in which I need to define and insert a function with variable arguments. Can I do it with the help of getOrInsertFunction()? If not can someone tell me any other method?
It will be very helpful if anyone can help. Thanks in advance

Akshay Jain <jivan.molu@gmail.com> writes:

I am working on a pass in which I need to define and insert a function with
variable arguments. Can I do it with the help of getOrInsertFunction()?

Sure. There is an overload of getOrInsertFunction that takes a
FunctionType, and there are FunctionType::get static methods where you
say if the function type takes a variable number of arguments. See the
doxygen documentation for FunctionType and Module::getOrInsertFunction.

I have tried it, but I always end up with some kind of error. Can you explain how can I get a function type for function which returns void (nothing) and it’s arguments are (int, int, int, void *, void *, …) ??

Thanks in advance.

Akshay Jain <jivan.molu@gmail.com> writes:

I have tried it, but I always end up with some kind of error. Can you
explain how can I get a function type for function which returns void
(nothing) and it's arguments are (int, int, int, void *, void *, ...) ??

Instead of getting something to cut&paste, you would be much more
enriched if the problematic code and the resulting errors were shown for
examination.

The code that I have written to get the function type is:

const std::vector<Type *> ParamTys;
ParamTys.push_back(IntegerType::getInt32Ty(Context));
ParamTys.push_back(IntegerType::getInt32Ty(Context));
ParamTys.push_back(IntegerType::getInt32Ty(Context));
ParamTys.push_back(PointerType::get(Type::getVoidTy(Context), 0));
ParamTys.push_back(PointerType::get(Type::getVoidTy(Context), 0));

FunctionType *ftype = FunctionType::get(Type::getVoidTy(Context), ParamTys, true);

And the errors are:

/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp: In member function ‘virtual bool {anonymous}::Hello2::runOnFunction(llvm::Function&)’:
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:108:62: error: no matching function for call to ‘std::vectorllvm::Type*::push_back(const llvm::IntegerType*) const’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:108:62: note: candidate is:
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = llvm::Type*, _Alloc = std::allocatorllvm::Type*, std::vector<_Tp, _Alloc>::value_type = llvm::Type*]
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: no known conversion for argument 1 from ‘const llvm::IntegerType*’ to ‘llvm::Type* const&’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:109:62: error: no matching function for call to ‘std::vectorllvm::Type*::push_back(const llvm::IntegerType*) const’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:109:62: note: candidate is:
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = llvm::Type*, _Alloc = std::allocatorllvm::Type*, std::vector<_Tp, _Alloc>::value_type = llvm::Type*]
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: no known conversion for argument 1 from ‘const llvm::IntegerType*’ to ‘llvm::Type* const&’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:110:62: error: no matching function for call to ‘std::vectorllvm::Type*::push_back(const llvm::IntegerType*) const’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:110:62: note: candidate is:
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = llvm::Type*, _Alloc = std::allocatorllvm::Type*, std::vector<_Tp, _Alloc>::value_type = llvm::Type*]
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: no known conversion for argument 1 from ‘const llvm::IntegerType*’ to ‘llvm::Type* const&’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:111:75: error: no matching function for call to ‘std::vectorllvm::Type*::push_back(llvm::PointerType*) const’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:111:75: note: candidate is:
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = llvm::Type*, _Alloc = std::allocatorllvm::Type*, std::vector<_Tp, _Alloc>::value_type = llvm::Type*]
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: no known conversion for implicit ‘this’ parameter from ‘const std::vectorllvm::Type*’ to ‘std::vectorllvm::Type*
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:112:75: error: no matching function for call to ‘std::vectorllvm::Type*::push_back(llvm::PointerType*) const’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:112:75: note: candidate is:
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = llvm::Type*, _Alloc = std::allocatorllvm::Type*, std::vector<_Tp, _Alloc>::value_type = llvm::Type*]
/usr/include/c++/4.6/bits/stl_vector.h:826:7: note: no known conversion for implicit ‘this’ parameter from ‘const std::vectorllvm::Type*’ to ‘std::vectorllvm::Type*
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:114:91: error: no matching function for call to ‘llvm::FunctionType::get(const llvm::Type*, const std::vectorllvm::Type*&, bool)’
/home/akshay/llvm/llvm-2.9/lib/Transforms/AliasPass/pass2.cpp:114:91: note: candidates are:
/home/akshay/llvm/llvm-2.9/include/llvm/DerivedTypes.h:157:24: note: static llvm::FunctionType* llvm::FunctionType::get(const llvm::Type*, const std::vector<const llvm::Type*>&, bool)
/home/akshay/llvm/llvm-2.9/include/llvm/DerivedTypes.h:157:24: note: no known conversion for argument 2 from ‘const std::vectorllvm::Type*’ to ‘const std::vector<const llvm::Type*>&’

It may be a silly mistake, but I am quite new to c and c++ coding especially in llvm. So I will be very grateful if you can help out.

Akshay Jain <jivan.molu@gmail.com> writes:

The code that I have written to get the function type is:

const std::vector<Type *> ParamTys;

You are declaring a constant vector...

ParamTys.push_back(IntegerType::getInt32Ty(Context));

... and then you try to modify it by pushing back an element. Remove the
`const' from the std::vector declaration.

ParamTys.push_back(IntegerType::getInt32Ty(Context));
ParamTys.push_back(IntegerType::getInt32Ty(Context));
ParamTys.push_back(PointerType::get(Type::getVoidTy(Context), 0));

There is no "pointer to void" in the LLVM type system. Use a pointer to
byte:

ParamTys.push_back(PointerType::get(Type::getInt8Ty(Context), 0));

ParamTys.push_back(PointerType::get(Type::getVoidTy(Context), 0));

Same.

FunctionType *ftype = FunctionType::get(Type::getVoidTy(Context), ParamTys,
true);

This looks good.

And the errors are:

[snip]

It may be a silly mistake, but I am quite new to c and c++ coding
especially in llvm. So I will be very grateful if you can help out.

Using LLVM without a solid background in C++ is a tough task.

You don't need to know about template metaprogramming, but an
understanding of classes (and the C++ type system in general) and some
familiarity with the idioms of the C++ Standard Library is essential.

A good method for familiarizing yourself with the LLVM API is to feed
clang with some C or C++ source code that uses the feature you are
interested in and then use llc for obtaining the LLVM C++ code that
generates the corresponding LLVM intermediate representation. For this
specific case:

/* foo.c */
void foo(int, int, void*, void*, ...) {
  return;
}
/* end of foo.c */

clang -emit-llvm -c foo.c -o foo.ll
llc -march=cpp foo.ll -o foo.ll.cpp

Now look into foo.ll.cpp