I want to write some code that, given an LLVM function F, creates an exact copy in the same module (so the copy can be manipulated later while preserving the original). I want to do this with the CloneFunctionInto method.
My current attempt involves trying to insert each (new arg,old arg) pair into the VMap. Previously I've tried inserting an uninitialised VMap and putting the pair the other way round. Impressively, all 3 have resulted in the exact same error message:
Assertion `VMap.count(&I) && "No mapping from source argument specified!"' failed.
//F and S are defined higher up in the code
FunctionType *FType = F->getFunctionType();
Function *new_F = cast<Function>(M->getOrInsertFunction(S,FType));
std::vector<Type*> ArgTypes;
ValueToValueMapTy VMap;
Function::arg_iterator old_args = F->arg_begin();
for (Function::arg_iterator new_args = new_F->arg_begin(), new_args_end = new_F->arg_end();new_args != new_args_end; new_args++) {
std::pair<Value*,Value*> pair(&*new_args,&*old_args);
VMap.insert(pair);
if (VMap.count(&*new_args)>0) {
errs().write_escaped("Mapping added") << '\n';
}
old_args++;
}
SmallVector<ReturnInst*, 8> Returns;
CloneFunctionInto(new_F, F, VMap, false, Returns, "_new", 0, 0);
In use, the 'mapping added' message is printed the correct number of times (i.e. once for each argument), so I'm really unsure where the error is.
You can use CloneFunction instead of CloneFunctionInto when you just want to clone a function.
Also CloneFunction shows you how to handle a ValueToValueMap for cloning:
From CloneFunction.cpp:
00223 Function *llvm::CloneFunction(const Function *F, ValueToValueMapTy &VMap,
00224 bool ModuleLevelChanges,
00225 ClonedCodeInfo *CodeInfo) {
00226 std::vector<Type*> ArgTypes;
00227
00228 // The user might be deleting arguments to the function by specifying them in
00229 // the VMap. If so, we need to not add the arguments to the arg ty vector
00230 //
00231 for (const Argument &I : F->args())
00232 if (VMap.count(&I) == 0) // Haven't mapped the argument to anything yet?
00233 ArgTypes.push_back(I.getType());
00234
00235 // Create a new function type...
00236 FunctionType *FTy = FunctionType::get(F->getFunctionType()->getReturnType(),
00237 ArgTypes, F->getFunctionType()->isVarArg());
00238
00239 // Create the new function...
00240 Function *NewF = Function::Create(FTy, F->getLinkage(), F->getName());
00241
00242 // Loop over the arguments, copying the names of the mapped arguments over...
00243 Function::arg_iterator DestI = NewF->arg_begin();
00244 for (const Argument & I : F->args())
00245 if (VMap.count(&I) == 0) { // Is this argument preserved?
00246 DestI->setName(I.getName()); // Copy the name over...
00247 VMap[&I] = &*DestI++; // Add mapping to VMap
00248 }
00249
00250 if (ModuleLevelChanges)
00251 CloneDebugInfoMetadata(NewF, F, VMap);
00252
00253 SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned.
00254 CloneFunctionInto(NewF, F, VMap, ModuleLevelChanges, Returns, "", CodeInfo);
00255 return NewF;
00256 }
Related
I'm trying to write a plugin that adds support for [[invariant]] contracts in classes/structs to complete the Contracts support that was added recently in GCC.
This boils down to basically translating something like the below:
class Heap {
private:
// ... fields
[[invariant]]
void check_invariants()
{
assert(size >= 0);
assert(capacity >= 0);
assert(size <= capacity);
}
public:
// constructor, push, pop, etc
};
Into a form where calls to this->invariant(); are made on the entry/exit of every member function that is not the [[invariant]] method itself.
So e.g., push() becomes:
void push(int value)
{
this->check_invariants(); // AUTO-GENERATED
data[size] = value;
size++;
this->check_invariants(); // AUTO-GENERATED
}
Now, I've managed to get most of this functionality I think, but I'm running into an issue where I can't seem to get the insertion of the call to this->check_invariants(); to work.
What I have is:
/**
* Create a function call to 'this->invariant()' and insert it before the given
*/
static void
insert_instrumentation_fn(gimple* curr_stmt)
{
tree ctype = DECL_CONTEXT(current_function_decl);
tree fn_decl = lookup_member(ctype, // class type
get_identifier("invariant"), // function name
1, // allow protected access
0, // do not raise error if not found
tf_warning_or_error // error handling
);
// Extract the function declaration from the member function
if (TREE_CODE(fn_decl) == BASELINK)
{
fn_decl = BASELINK_FUNCTIONS(fn_decl);
}
// build new method call
// call is of the form: this->invariant()
// Get the 'this' pointer
tree this_ptr = cp_build_fold_indirect_ref(DECL_ARGUMENTS(current_function_decl));
vec<tree, va_gc>* args = make_tree_vector_single(this_ptr);
tree call = build_new_method_call(this_ptr, // object
fn_decl, // function
&args, // arguments
NULL_TREE, // conversion function
LOOKUP_NORMAL,
NULL, // function decl
tf_warning_or_error);
// build gimple call
gimple* call_stmt = gimple_build_call(call, 0);
// insert call before current statement
gimple_stmt_iterator gsi = gsi_for_stmt(curr_stmt);
gsi_insert_before(&gsi, call_stmt, GSI_SAME_STMT);
}
The issue is that this code produces an error like the below:
[build] > Inspecting function '__ct_base '
[build] Found invariant attribute: invariant
[build] adding function call before *this_3(D) ={v} {CLOBBER};
[build] /home/user/projects/gcc-invariant-plugin/test/test.cpp: In constructor 'Heap::Heap(int)':
[build] /home/user/projects/gcc-invariant-plugin/test/test.cpp:66:1: error: call to non-function 'void Heap::invariant()'
NOTE: I based this code off of examples in the GCC gcc/cp/coroutines.cc code generator I found:
tree ash_m = lookup_member (coro_frame_type, coro_self_handle_id, 1,
0, tf_warning_or_error);
tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
false, tf_warning_or_error);
/* So construct the self-handle from the frame address. */
tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
0, tf_warning_or_error);
r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
vec<tree, va_gc> *args = make_tree_vector_single (r);
tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
NULL, tf_warning_or_error)
I have a class Frobnicator that handles various requests.
class Frobnicator
{
public:
// Handlers are member functions.
// They optionally take some input. They optionally return some output. But they always take the context!
// There are more types than just int involved, but it's always just one input or void, and one output or void.
void performSomething(Context* context) { /* ... */ } // Takes void, returns void
void setSomething (Context* context, int input) { /* ... */ } // Takes int , returns void
int getSomething (Context* context) { /* ... */ } // Takes void, returns int
int convertSomething(Context* context, int input) { /* ... */ } // Takes int , returns int
template<typename TResult, typename TParameter>
void registerHandler(std::string identifier, TResult(Frobnicator::* handler)(Context*, TParameter))
{
// The external API actually wants a callback that takes and returns JSON. We give it a lambda that does the conversion and calls the actual member function.
// The identifier tells the external API which callback to call for which request. It's not relevant for this question, just to show the idea. Think of something like a REST API.
someExternalApiThatWantsJson.registerHandler(identifier, [&](Context* context, Json input)
{
// Idealy, this would be a one-liner.
//return Json::convertFrom((this->*handler)(context, input.convertTo<TParameter>()));
// But calling Json.convertTo<void>() and Json::convertFrom(void) does not work automagically anyways, so we need to split it up manually:
Json result;
if constexpr (std::is_same<TResult, void>::value)
if constexpr (std::is_same<TParameter, void>::value) (this->*handler)(context ) ; // Takes void, returns void
else (this->*handler)(context, input.convertTo<TParameter>()) ; // Takes something, returns void
else
if constexpr (std::is_same<TParameter, void>::value) result = Json::convertFrom((this->*handler)(context )); // Takes void, returns something
else result = Json::convertFrom((this->*handler)(context, input.convertTo<TParameter>())); // Takes something, returns something
return result;
});
}
// Set up the handlers.
void setup()
{
// The problem is that some of these calls don't work:
registerHandler ("PerformSomething", &Frobnicator::performSomething); // "failed template argument deduction"
registerHandler<void, void>("PerformSomething", &Frobnicator::performSomething); // Trying to specify the types explicitly: "substitution failure [with TResult = void, TParameter = void]: argument may not have 'void' type"
registerHandler ("SetSomething" , &Frobnicator::setSomething); // Compiles fine
registerHandler ("GetSomething" , &Frobnicator::getSomething); // "failed template argument deduction"
registerHandler<int , void>("GetSomething" , &Frobnicator::getSomething); // Trying to specify the types explicitly: "substitution failure [with TResult = int, TParameter = void]: argument may not have 'void' type"
registerHandler ("ConvertSomething", &Frobnicator::convertSomething); // Compiles fine
}
};
TResult can be int or void and it works fine. But it only works when TParameter isn't void.
How can I make registerHandler also accept pointers to functions that take no arguments?
The idea is to have the member functions' signatures very clean and the calls to registerHandler mostly clean. So giving performSomething and getSomething a dummy parameter is out of the question. Manually specifying the types when calling registerHandler is ugly but I'll accept it, if it's necessary.
The body of registerHandler is relatively short and mostly deals with distinguishing void from non-void anyways, so providing a specialization for when TParameter is void would be a fine solution:
template<typename TResult>
void registerHandler<TResult, void>(std::string identifier, TResult(Frobnicator::* handler)(Context*))
Except that "function template partial specialization is not allowed".
Use template parameter pack to deal with void / non-void cases, since the number of arguments is indetermined (1 or 2).
template<typename TResult, typename... TParameter>
void registerHandler(std::string identifier, TResult(Frobnicator::* handler)(Context*, TParameter...))
The second parameter accepts a pointer to member function whose the first argument is required to be Context*, that's it.
Then,
void setup()
{
registerHandler ("PerformSomething", &Frobnicator::performSomething);
registerHandler ("SetSomething" , &Frobnicator::setSomething);
registerHandler ("GetSomething" , &Frobnicator::getSomething);
registerHandler ("ConvertSomething", &Frobnicator::convertSomething);
}
The implementation of registerHandler may also need some changes, the std::is_same_v<TParameter, void> can be replaced by sizeof...(TParameter) == 0.
Demo
Well. Sometimes you waste an hour because you narrowly miss a solution. Just don't make it a specification:
template<typename TResult>
void registerHandler(std::string identifier, TResult(Frobnicator::* handler)(Context*))
But!: This is a valid solution for me, but it would be nice to have a solution that does not require duplicating almost the entire function body. So better answers are absolutely welcome!
What I would do is follow the 0 1 infinity rule and write infinity instead of 2 cases.
Support any number of arguments. Map to tuples. Empty tuples for 0, mono for 1, etc.
Then the conversion code should work naturally. You can bind the call to be (take tuple, return tuple), then write the input/output code to handle 0, 1, or n from/to json.
Now the json function call logic no longer cares about void. The packing unpacking does. And the code that calls the raw function from tuples and packs it into a tuple return does.
template<class F>
auto packresult(F&&f){
if constexpr(f() is void)
f()
return tuple<>{};
else if constexpr(f returns a tuple)
return f();
else
return std::make_tuple(f());
}
Now you do the same for inputs
auto unpackargs(auto&&f){
return [f](auto&&tup){
return std::apply(f, tup);
}
}
which makes your code look like:
converttupletojson(packresult(bind(unpackargs(bind this to method), getargsfromjson<Args...>())))
and viola, the most surprising musical instrument.
I am writing a Function with 2 Parameters, 1st is integer type marked [[maybe_unused]] and 2nd is Boolean Type with Default Argument false.
int preOrderTraversial([[maybe_unused]] int searchData, bool forDisplay = false)
This is the function declaration. The function is used for pre-order Traversal in Binary Search Tree. I want to use the same function for Displaying the Tree and Traversing it for searching a Node with specific Data. But only for 1 of both problems at once. Not for searching AND displaying you see.
So, obviously, it works fine for the searching part but when I call the function for Displaying the function call looks like this:
preOrderTraversal(true)
or
bool forDisplay = true;
preOrderTraversal(forDisplay);
Now the Compiler (even with the parameter DECLARED as a BOOL) still considers this bool parameter as an int and uses it for searchData (integer) parameter of the function and not for the forDisplay (bool) parameter.
Is there a way to force or tell compiler which of both parameters I am trying to work with?
[[maybe_unused]] means that the function body may not use it, but the signature of the function always have it. Actually event the default value for the boolean does not modify the signature of your function; Thus your function always take 2 arguments, the first being a integer, and the second being a boolean (that may be set to the default if you didn't put it). You end up with calling:
bool forDisplay = true;
preOrderTraversal(/* integer searchData; bool geting casted to int */ forDisplay,
false /* the forDisplay (2nd param) default value*/);
which does not meet your expectations.
[EDIT]
how to overcome?
There is not builtin way to use named parameters in C++ but you may workaround using a helper class:
struct PreOrderTraversal {
bool _forDisplay = false;
int _searchData = 0; /* FIXME What is the default here? */
auto& forDisplay() { _forDisplay = true; return *this; }
auto& searchData(int x) { _searchData = x; return *this; }
void run() { if (_forDisplay) ;//do the right things
else ;// use data
}
};
then you can use it with:
PreOrderTraversal().forDisplay().run();
PreOrderTraversal().searchData(123).run();
This kinda mimics that named parameter feature.
Still many C++ codes are so difficult for me to understand..
Below is a code snippet from dlib (http://dlib.net file : dlib/external/pybind11/include/pybind11/pybind11.h)
It's a member function definition of class cpp_function and I didn't try to understand the code(no time to do that..that's sad..). I can't understand the syntax in the line I put *** this line! comment at below. I understand the lambda function(unnamed function), so is it assigning a function pointer to rec->impl, the function taking function_call &call as argument and returning handle? So, it looks like defining a function and at the same time assigning the function pointer to a variable. Having asked it, it looks so now.. Please someone confirm this.
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
using namespace detail;
struct capture { remove_reference_t<Func> f; };
...
rec->impl = [](function_call &call) -> handle { // <=== *** this line!
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args_converter.load_args(call))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
process_attributes<Extra...>::precall(call);
/* Get a pointer to the capture object */
auto data = (sizeof(capture) <= sizeof(call.func.data)
? &call.func.data : call.func.data[0]);
capture *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
const auto policy = return_value_policy_override<Return>::policy(call.func.policy);
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t<Extra...>;
/* Perform the function call */
handle result = cast_out::cast(
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
/* Invoke call policy post-call hook */
process_attributes<Extra...>::postcall(call, result);
return result;
};
...
using FunctionType = Return (*)(Args...);
constexpr bool is_function_ptr =
std::is_convertible<Func, FunctionType>::value &&
sizeof(capture) == sizeof(void *);
if (is_function_ptr) {
rec->is_stateless = true;
rec->data[1] = const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
}
}
rec->impl = [](function_call &call) -> handle
creates a lambda which takes one argument of type function_call and returns a handle, then assigns it to rec->impl.
As lambdas are basically unnamed structs, they also have unnamed types. Since rec->impl obviously exists already and is thus not templatized on the lambda type, the lambda gets converted to some other type during the assignment. (Note: there could however be a templatized and overloaded operator= here)
Typically such types which can take lambdas are either std::function or function pointers as stateless lambdas can be converted to function pointers.
I have a question about modifying elements in boost::multi_index container.
What I have is the structure, containing some pre-defined parameters and
a number of parameters, which are defined at run-time, and stored in a map.
Here is a simplified version of the structure:
class Sdata{
QMap<ParamName, Param> params; // parameters defined at run-time
public:
int num;
QString key;
// more pre-defined parameters
// methods to modify the map
// as an example - mock version of a function to add the parameter
// there are more functions operating on the QMAP<...>, which follow the same
// rule - return true if they operated successfully, false otherwise.
bool add_param(ParamName name, Param value){
if (params.contains(name)) return false;
params.insert(name, value);
return true;
}
};
Now, I want to iterate over different combinations of the pre-defined parameters
of Sdata. To do this, I went for boost::multi_index:
typedef multi_index_container<Sdata,
indexed_by <
// by insertion order
random_access<>,
//by key
hashed_unique<
tag<sdata_tags::byKey>,
const_mem_fun<Sdata, SdataKey, &Sdata::get_key>
>,
//by TS
ordered_non_unique<
tag<sdata_tags::byTS>,
const_mem_fun<Sdata, TS, &Sdata::get_ts>
>,
/// more keys and composite-keys
>//end indexed by
> SdataDB;
And now, I want to access and modify the parameters inside the QMap<...>.
Q1 Do I get it correctly that to modify any field (even those unrelated to
the index), one needs to use functors and do something as below?
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, Functor(...))
Q2 How to get the result of the method using the functor? I.e., I have a functor:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
sdata.remove_param (name); // this returns false if there is no param
}
};
How to know if the remove_param returned true or false in this example:
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, SdataRemoveParam("myname"));
What I've arrived to so far is to throw an exception, so that the modify
method of boost::multi_index, when using with Rollback functor will return
false:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
if (!sdata.remove_param (name)) throw std::exception("Remove failed");
}
};
// in some other place
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
bool res = l.modify(it, SdataRemoveParam("myname"), Rollback);
However, I do not like the decision, because it increases the risk of deleting
the entry from the container.
Q3 are there any better solutions?
Q1 Do I get it correctly that to modify any field (even those
unrelated to the index), one needs to use functors and do something as
below?
Short answer is yes, use modify for safety. If you're absolutely sure that the data you modify does not belong to any index, then you can get by with an ugly cast:
const_cast<Sdata&>(*it).remove_param("myname");
but this is strongly discouraged. With C++11 (which you seem to be using), you can use lambdas rather than cumbersome user-defined functors:
Sdatas_byKey &l = sdatas.get<sdata_tags::byKey>(); // note, this can't be const
auto it = l.find(key);
l.modify(it, [](Sdata& s){
s.remove_param("myname");
});
Q2 How to get the result of the method using the functor?
Again, with lambdas this is very simple:
bool res;
l.modify(it, [&](Sdata& s){
res=s.remove_param("myname");
});
With functors you can do the same but it requires more boilerplate (basically, have SdataRemoveParam store a pointer to res).
The following is just for fun: if you're using C++14 you can encapsulate the whole idiom very tersely like this (C++11 would be slightly harder):
template<typename Index,typename Iterator,typename F>
auto modify_inner_result(Index& i,Iterator it,F f)
{
decltype(f(std::declval<typename Index::value_type&>())) res;
i.modify(it,[&](auto& x){res=f(x);});
return res;
}
...
bool res=modify_inner_result(l,it, [&](Sdata& s){
return s.remove_param("myname");
});