get analysis result with LLVM LegacyPassManager - c++

I'm currently writing a program that uses LLVM but is not a pass itself. For that, I want to utilize several analysis passes but not from a pass context.
As a concrete example I want to use the RegionInfo information that the RegionInfoPass can give me.
Now I have seen that LLVM has two PassManagers, a new one and an old one. If I get it right, the extraction of the RegionInfo -- given the new PassManager -- should be working with the following code (more less) (source):
void called_from_out_of_llvm(llvm::Function& f) {
llvm::PassBuilder pb;
llvm::FunctionAnalysisManager fam;
pb.registerFunctionAnalyses(fam);
llvm::RegionInfo& ri = fam.getResult<llvm::RegionInfoPass>(f);
}
However, this does not work since RegionInfoPass is an old pass so it has to be used with the old PassManager.
As far as I can see, the only way to retrieve analysis results with the old PassManager is to call getAnalysis<Pass> within another pass. Therefore I tried to create a wrapper pass and call it:
#include <llvm/Analysis/RegionInfo.h>
#include <llvm/IR/LegacyPassManager.h>
#include <cassert>
template <typename P, typename Result>
class AnalysisResult;
/* This implements a dummy pass that retrieves the requested analysis and
* "leaks" it to the AnalysisResult instances which creates the pass.
*/
template <typename P, typename Result>
struct Extractor : public llvm::FunctionPass {
AnalysisResult<P, Result>& result;
std::function<Result&(P*)> analysis_func;
static char ID;
Extractor(AnalysisResult<P, Result>& result, std::function<Result&(P*)> analysis_func) : llvm::FunctionPass(ID), result(result), analysis_func(analysis_func) {}
virtual void getAnalysisUsage(llvm::AnalysisUsage& au) const override { au.addRequired<P>(); }
bool runOnFunction(llvm::Function& func) override {
P& p = getAnalysis<P>();
Result& res = analysis_func(&p);
result.result = &res;
return false;
}
};
template <typename P, typename Result>
char Extractor<P, Result>::ID = 0;
/* This constructs the legacy PassManager, add the dummy pass from above and runs it. */
template <typename P, typename Result>
struct AnalysisResult {
llvm::legacy::FunctionPassManager fpm;
std::function<Result&(P*)> analysis_func;
Result* result = nullptr;
AnalysisResult(llvm::Function& func, std::function<Result&(P*)> f) : fpm(func.getParent()), analysis_func(f) {
fpm.add(new Extractor<P, Result>(*this, analysis_func));
fpm.doInitialization();
fpm.run(func);
}
~AnalysisResult() { fpm.doFinalization(); }
Result& get_result() {
assert(result != nullptr);
return *result;
}
};
/* This is just a convenience function that tries to mimic the interface of the new PassManager */
template <typename P, typename Result>
AnalysisResult<P, Result> getLLVMAnalysis(llvm::Function& func, std::function<Result&(P*)> f) {
// afaik this moves implicitly
return AnalysisResult<P, Result>(func, f);
}
/* getRegionInfo is overloaded so provide this as wrapper to
* make the function pointer cast to std::function possible
*/
RegionInfo& dummy_function(RegionInfoPass* rip) {
return rip->getRegionInfo();
}
/* The actual program function that uses all of the above helper constructs. */
void called_from_out_of_llvm(llvm::Function& f) {
llvm::PassRegistry& registry = *llvm::PassRegistry::getPassRegistry();
initializeAnalysis(registry);
AnalysisResult<RegionInfoPass, RegionInfo> ar = getLLVMAnalysis<RegionInfoPass, RegionInfo>(f, dummy_function);
RegionInfo& ri = ar.get_result();
ri.view(); // this segfaults
}
The problem with this code is that it segfaults when I want to use the analysis result. I'm not really sure why this happens, but it seems that the analysis result gets deleted directly in the fpm.run() function. However, replacing fpm.run() is not trivial (I thought of subclassing) because it is implemented with PImpl in an non public subclass.
Can you give me a hint if it is possible to run an analysis pass and use the result out of a pass context?

Related

Does C++ support parameterized function for testing purpose?

I have a lengthy unit test code snippet that I want to run for two functions. I am wondering if there's a way to do this without copy and paste the code and only change the function name?
Say the test code looks like
int main(){
output1 = function(input1);
assert output1 == answer1;
output2 = function(input2);
assert output2 == answer2;
output3 = function(input3);
assert output3 == answer3;
......
outputN = function(inputN);
assert outputN == answerN;
}
Now say I have two function func1 and func2. I want to ran literally the same test for func1 and func2. I am wondering if there's a neat way to do this in C++ without involving some test framework? Thanks in advance for any help.
You can make a function template:
template <typename F, typename R, typename Args...>
void test_func(F f, R&& r, Args&&... args) {
auto output = f(std::forward<Args>(args)...);
assert(output == std::forward<R>(r));
}
then use it like
test_func(&func1, answer1, input1);
test_func(&func2, answer2, input2);
...
Additional explanations:
The parameters and return value are passed by forwarding reference, then their value categories will be reserved when being passed to the function (with the usage of std::forward).
The parameters is declared as parameter pack then you can pass multiple ones with any types.
C++ supports passing parameters to functions ;).
You can pass functions to functions. To keep it simple, I am assuming that all functions you want to test have the same signature. To avoid verbose syntax of function pointers I'd use a template:
template <typename F>
void test_function(F f, std::vector<input_type> input,std::vector<output_type> expected) {
for (size_t i = 0; i < input.size(); ++i) {
assert( f(input[i]) == expected[i]);
}
}
int main() {
test_function( func1, {1,2,3},{2,3,4} );
test_function( func2, {1,2,3},{6,7,8} );
}
PS: From my own experience I can tell you that it isn't worth to put much work into hand-written test facilities. You will find yourself wanting more and more features that a test framework offers out of the box (eg logging test reports). Googletest is something I can recommend.
A solution of C methed is to use fuction pointer. But I recommand lambda fuction pulished in c++11. u can use as follow:
template<typename Func>
void test(intput in, output out, Func func) {
answer = func(in);
assert(out == answer);
}
void main() {
intput intput1;
output output1;
test(input1, output1, [&](intput in)->output{return func1(in)});
test(input1, output1, [&](intput in)->output{return func2(in)});
}
After all, u should add compile para:-std=c++11 while using g++ compiler.
Here's my new take, this should compile. It's built in layers so you can see how to expand each layer as you see fit. It doesn't work exactly as your example does, there are copies being made of your input data and there is no assignment operation for the output. You should take these into account and adjust accordingly (if required).
// Example program
#include <functional>
#include <assert.h>
#include <vector>
#include <utility>
// function to test
int func1(int p_param)
{
return p_param;
}
// function to test
int func2(int p_param)
{
return p_param;
}
// Test runner base
template <typename TFunction, typename TInput, typename TOutput>
void test_runner(TFunction f, std::vector < std::pair<TInput, TOutput> > p_testparameters)
{
for (auto pair : p_testparameters)
{
assert(f(pair.first) == pair.second);
}
}
// Specific test 1
template <typename TFunction>
void test1(TFunction f)
{
test_runner<TFunction, int, int>(f, { {1,1},{2,2},{3,3} });
}
// Specific test 2
template <typename TFunction>
void test2(TFunction f)
{
test_runner<TFunction, int, int>(f, { {10,10},{20,20},{30,30} });
}
// Run tests for function
template <typename TFunction>
void runTests(TFunction f)
{
test1(f);
test2(f);
}
int main() {
runTests(func1);
runTests(func2);
return 0;
}

Augment a class / apply an aspect in pure C++ (C++11)

Suppose I have a class:
class Widget {
public:
void initialize() {
// hurr-durr
};
int computeAnswer() {
return -42;
};
std::string getQuestion() {
return "The question";
};
};
It performs some computation, can do whatever it wants.
Now I want to augment it - apply an aspect, say one that logs each method call.
If I implemented this by hand, I'd implement all methods in this fashion:
int LoggingWidget::computeAnswer(){
log << 'Calling method computeAnswer';
int result = Widget::computerAnswer();
log << 'Result = ' << result;
return result;
}
I'd like the solution to be as generic as possible (I don't want to manually forward all calls), so the possible usages could include one of these (whichever is possible)
Widget* w = new LoggingWidget(); // either a class that inherits from Widget
// and automatically forwards all calls.
Widget* w = new Logging<Widget>(); // or a template that does this.
so that when I call
int result = w.computeAnswer();
The calls will be logged. Perhaps the new ellipsis operator (...) could come in handy here?
This isn't directly possible, since you can't inspect a class to see which members it has.
However, you can do something close:
Logging<Widget> w(widget);
w([&](Widget& w){
return w.computeAnswer();
});
Where Logging::operator() looks like follows:
/* somewhere in class: T wrapped; */
template<class F>
auto operator()(F&& f)
-> decltype(f(wrapped))
{
pre_log();
auto&& result = f(wrapped);
post_log(result);
return result;
}
It won't get better much better than this for totally generic code, since C++ has no (static) reflection.
Expanding on Xeo's answer, if you use decltype or result_of rather than auto && you also get copy elision.
template<typename F>
auto operator()(F &&f) -> decltype(std::forward<F>(f)(wrapped))
{
pre_log();
decltype(std::forward<F>(f)(wrapped)) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}
In C++14 you can shorten this to:
template<typename F>
decltype(auto) operator()(F &&f)
{
pre_log();
decltype(auto) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}

Wrapping C functions in auto objects without code duplication

In C++03, when you were to wrap a bunch of C functions in a class to create an 'auto object', you had to customize the object to the type of functions it encapsulated. As an example, to wrap a windows file HANDLE, you needed to call CloseHandle() in the destructor and CreateFile() in the constructor. The constructor would need to mimic the function signature of the CreateFile() function, sans the file HANDLE variable (since it's being managed).
Anyway, what I'd like to know is if it's possible to use the new features of C++11 to create a single generic class that can be used to wrap any type of resource by only providing an implementation for creation and deletion?
One problem I foresee is that the creation function, such as noted above with CreateFile(), can taken any number of parameters. Is there a way to auto-magically generate a templated constructor that mimics the signature of the function? Variadic Parameters come to mind, but I have not yet used them.
Has anyone tried writing something like this?
EDIT: Some code to help illustrate (pseudo):
template<typename Res, FunctionPtrToCreatorFunc Func, typename... Arguments>
class creator
{
public:
operator()(Res &r, Arguments... Args)
{
Func(r, /*use args?*/ Args); // Allocate resource, ie. CreateFile(r, args)
}
};
template<typename Res, FunctionPtrToDeleterFunc Func>
class deleter
{
operator()(Res &r)
{
Func(r); // delete the resource, ie. CloseHandle(r)
}
};
Then this will be the implementation of my super auto object:
template<typename Res, typename Creator, typename Deleter>
class auto_obj
{
public:
auto_obj(/*somehow copy Args from Creator class?*/)
{
Creator(_res, /*args?*/);
}
~auto_obj()
{
deleter(_res);
}
Res _res;
};
Yes, this has a similar structure to shared_ptr or unique_ptr, but instead the constructor will be the one that creates the resources by developer written creator and deleter classes. I have a feeling that std::bind may play a role in this, but I have never used it.
Here is a stab at it:
#include <utility>
#include <type_traits>
#include <cstddef>
A more friendly way to wrap up a function. I move the signature boilerplate to this template, instead of messing up the actual RAII class below. This also allows full fledged function objects to be used, as well as functions, in the RAII class below:
template< typename FuncSig, FuncSig func >
struct Functor {
template<typename... Args>
auto operator()(Args&&... args) const
-> decltype( func(std::forward<Args>(args)...) )
{ return ( func(std::forward<Args>(args)...) ); }
};
One operation that is needed for more than basic functionality is the ability to "null" a handle, allowing invalid handles to exist, and allowing handles to be moved around. Zeroer is my default function object for "null"ing a handle:
struct Zeroer {
template<typename T>
void operator()( T& t ) const {
t = 0;
}
};
RAII_handle herself. You pack the creation and destruction signatures into it, and it forwards construction to the underlying data. .close() lets you close the RAII_handle early, which is a common requirement in practice. You access the underlying data via operator* or operator->, and while this makes it look pointer-like, RAII_handle does not obey pointer semantics. It is a move-only type.
template< typename T, typename Creator, typename Destroyer, typename Nuller=Zeroer >
struct RAII_handle {
RAII_handle( std::nullptr_t ):
data()
{
Nuller()(data);
}
RAII_handle( RAII_handle const& ) = delete;
RAII_handle( RAII_handle && o ):data(std::move(o.data)) {
Nuller()(o.data);
}
RAII_handle& operator=( RAII_handle const& ) = delete;
RAII_handle& operator=( RAII_handle && o ) {
data = std::move(o.data);
Nuller()(o.data);
return *this;
}
template<typename... Args>
RAII_handle( Args&&... args ):
data( Creator()(std::forward<Args>(args)...) )
{}
auto close()->decltype( Destroyer()(std::declval<T&>()) ) {
auto retval = Destroyer()(data);
Nuller()(data);
return retval;
}
~RAII_handle() {
close();
}
T& get() { return data; }
T const& get() const { return data; }
T& operator*() { return get(); }
T const& operator*() const { return get(); }
T* operator->() { return &get(); }
T const* operator->() const { return &get(); }
private:
T data;
};
Now, some test code. My file handles will be unsigned char, and opening/closing will simply test if things are not working right.
#include <iostream>
typedef unsigned char HANDLE;
HANDLE CreateFile( char const* name ) {
std::cout << name << "\n";
return 7;
}
bool CloseFile( HANDLE h ) {
if (h) {
--h;
std::cout << (int)h << "\n";
return true;
} else {
std::cout << "already closed\n";
return true;
}
}
Once you have your open/close functions or function objects, here is how you make the type of the FileHandle:
typedef RAII_handle< HANDLE, Functor< HANDLE(*)( char const* ), CreateFile >, Functor< bool(*)(HANDLE), CloseFile > > FileHandle;
You can support entire overload sets by simply creating a function object that forwards to a fixed function name, instead of to a fixed function pointer. Basically take Functor above, remove the template signature and pointer, and replace the use of func with actual use of your function name.
Suddenly your function object represents not calling one function, but calling an entire overload set.
Fancier work can even support multiple functions, allowing one function object to support calling either CreateFile or CreateFileEx depending on what arguments are passed in.
And here is our trivial test code:
int main() {
FileHandle bob("hello.txt");
HANDLE value = *bob; // get the HANDLE out of the FileHandle
bob.close(); // optional, to close early
}
Requirements: your CloseFile must accept Nuller()(std::declval<T&>()) and not behave badly. The default Nuller()(...) just assigns zero to your T, which works for many handle types.
It supports move semantics, allowing you to return these from a function, but I didn't include a Copier argument (which I'd expect would be required for any RAII objects that can be copied).
Live example with very slightly different code.

using boost::function to save function pointer to arbitrary object's member functions

I am trying to store a member function from an object to call it when an appropriate event happens. Unfortunately this code gives a lot of error messages. Can anybody help me?
class MainPage
{
public:
MainPage::MainPage(void)
{
image1 = new STImagePanel("Untitled.png");
image1->OnPointerPressedHandler->add(&MainPage::imageMousePressed,this);
}
void MainPage::imageMousePressed(STObject* sender, STPointerEventArg * args)
{
MainPage * dsda = (MainPage*)this;
pres = true;
}
};
template<class SENDERTYPE, class ARG>
struct callbackInfo
{
boost::function<void(SENDERTYPE, ARG)> func;
};
template<class SENDERTYPE, class ARG>
class STEventHandler
{
public:
template<class T, class P>
void add(T x, P that)
{
//The following line gives the error
callbackInfo<SENDERTYPE,ARG> tmp { boost::bind(x,that,_2)};
functions->addLast(tmp);
}
private:
STLinkedList<callbackInfo<SENDERTYPE,ARG>>* functions;
}
This gives the following errors:
http://pastie.org/8014181
Update:
with the following correction it works fine:
template<class T, class P>
void add(T x, P that)
{
boost::function<void(SENDERTYPE,ARG)> func(boost::bind(x,that,_1,_2));
callbackInfo<SENDERTYPE,ARG> tmp;
tmp.func = func;
}
One problem that I see MainPage::imageMousePressed(STObject* sender, STPointerEventArg * args) has two arguments, but in the call to boost::bind, you're only binding _2 to sender. That's doesn't work. You have to either bind both, or pass NULL or some sentinel value.
More generally, it looks to me like you're reinventing boost::signals
Two suggestions:
1) In code you did not show the first error message may have prevented some header inclusion;
2) You lack a semi-colon at the end of your class MainPage definition.

boost::bind with null function pointers

If the function pointer embedded in a boost::bind return object is NULL/nullptr/0, I need to take action other than calling it. How can I determine if the object contains a null function pointer?
Addenda
I don't believe I can use and compare boost::functions as the boost::bind return object is used with varying call signatures in a template function.
Simplified example:
template <typename BRO>
Retval do_stuff(BRO func, enum Fallback fallback)
{
if (func == NULL)
{
return do_fallback(fallback);
}
else
{
return use_retval(func());
}
}
do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), fallback);
Solution
Since the arity of the function in the callee does not change, I can "cast" the bind return object into a boost::function and call .empty()
Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback)
{
if (func.empty())
return do_fallback(fallback);
else
return use_retval(func());
}
You can either bind to a dummy function:
void dummy() { /* has differing behaviour */ }
// ...
boost::bind(&dummy)();
... or, assuming you're using Boost.Bind together with Boost.Function, return a default constructed function object and check for empty() before calling it:
typedef boost::function<void (void)> F;
F create() { return F(); }
void use() {
F f = create();
if(f.empty()) {
/* ... */
}
}
Regarding the update:
I still don't see what the problem with binding to a different function like the following would be:
template <typename BRO>
Retval do_stuff(BRO func)
{
return func();
}
if(funcPtr) {
do_stuff(boost::bind(&use_retval, boost::bind(funcPtr, a, b)));
} else {
do_stuff(boost::bind(&do_fallback, fallback));
}
If you'd want to move that handling out of the calling code, you could emulate variadic template function to support variable arities:
template<class R, class T1>
boost::function<R (T1)>
bind_wrap(R (*fnPtr)(), T1& t1, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1));
else return boost::bind(&do_fallback, fallback);
}
template<class R, class T1, class T2>
boost::function<R (T1, T2)>
bind_wrap(R (*fnPtr)(T1, T2), T1& t1, T2& t2, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1, t2));
else return boost::bind(&do_fallback, fallback);
}
// ... etc. for all needed arities
do_stuff(bind_wrap(funcPtr, var1, var2, fallback));
... or you use the approach above to generate boost::function<> objects or your own wrappers and check for functor.empty() or similar in do_stuff().
I'd create a wrapper object to do this. Something like the following
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
int aFunction(int i, int j)
{
std::cout<<"In a Function"<<std::endl;
return i+j;
}
struct DefaultingFromFnPtr : public boost::function< int(int,int) >
{
explicit DefaultingFromFnPtr( int(*fn)(int,int) ) : fn_(fn) {}
int operator()(int i, int j) const
{
if (fn_!=NULL) return fn_(i, j);
return 7;
}
int(*fn_)(int,int);
};
template<typename T>
void do_stuff( T t )
{
std::cout<<"RETURNED "<<t()<<std::endl;
}
int main( int argv, const char** argc)
{
int(*mightBeNullFnPtr)(int,int) = NULL;
if( argv>1)
{
mightBeNullFnPtr = & aFunction;
}
int var1 = 10;
int var2 = 20;
do_stuff( boost::bind( DefaultingFromFnPtr( mightBeNullFnPtr ), var1, var2 ) );
}
Compile this and run it with no arguments and it sets mightBeNullFnPtr to NULL and calls do_stuff with a wrapper class, and so prints out 7. Run it with an argument and it will set mightByNullFnPtr to aFunction and calls do_stuff with that, printing out 30.
If you want more genericity you will need to template the DefaultingFromFnPtr wrapper class, but that should be pretty easy to do.
I'm pretty sure calling boost::bind with a null pointer (= the creation of the bind object) should be considered undefined behavior, even if the crash only happens when calling it.
You're going to have to hack boost.
boost::bind returns unspecified-n-n. The only thing valid to do with these classes is operator(). The only other thing you know is that they are copy constructable, and have a typedef for result_type (which, by the way, means you don't need a template for result type).
You want something else - so you'll need to find the definition of unspecified-n-n in boost (there maybe several), hack them to have a is_null() member function which checks for the conditions you want, then call that as your test.
This is, of course, assuming you are certain you'll always get a boost::bind'ed object in your template function. If someone tries passing in a regular function pointer, it won't compile. Working around this will require some template magic.