Can I somehow get arguments passed to function in LLVM IR? - llvm

I want to move function call to other place in program, but i have a problem with arguments. I need get object associated with argument value.
Function *fu;
bool runOnModule(Module &M) override {
for(Function &a : M){
for(BasicBlock &b : a){
for(Instruction &i : b){
if(isa<CallInst>(i)){
fu = cast<CallInst>(i).getCalledFunction();
}
}
}
}
}
moveToOtherFunc(fu);
return true;
}
void moveToOtherFunc(Function *f){
...
BasicBlock *bb = ...
...
//now i must insert a arg object ( ArrayRef<Value*> arg )
//it is a list of objects representing func arguments
CallInst::Create(f,arg,"",bb);
}
So is there some function, that give me a list of arguments? Something like:
ArgumentsValueList a = f->getArgumentsValueObjectsAssociatedWithThisFunction();
I now that there is a Function::arg_iterator, but this give me just information about type and number of arguments, but no a object holding a value of argument, right? What i need to do, so i move call inst with arguments? Thanks

You can use the args() method in the Function class for your purpose.
It returns a pair of iterators for the start and the end of the argument list, through which you can iterate over all the arguments.

Related

Is it possible to access the arguments from an std::bind object?

Please consider the following scenario.
A hypothetical pop-up menu class that displays some actions, and when one of them is selected it will call the passed in action which is in form of an std::function:
PopupMenu::PopupMenu(std::function<void(RowItem*)> editRowFunction, RowItem *item)
: _editRowFunction(editRowFunction)
, _item(item) {
}
Then at some point it might call execute:
PopupMenu::execute(} {
_editRowFunction(_item);
}
Then I have this other class that's a UI object:
class EditorWidget {
void editRow(RowItem *row) {
//edit the row
}
}
And here's how I am using all of them:
int main() {
auto item = new RowItem();
auto editorWidget = new EditorWidget();
PopupMenu menu(std::bind(&EditorWidget::editRow, editorWidget, item), item);
menu.execute();
return 0;
}
Everything works. My question is the following:
If I am already passing the argument item in std::bind, why do I have to pass it again as a second parameter in order to be able to call the bound function with that argument? If I don't, and try to call the function just by itself from PopupMenu::execute(), I get a compiler error.
The other way around it is to make the constructor of PopupMenu like this:
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction) {}
And if I do it that way then I call it this way:
PopupMenu::execute() {
_editRowFunction();
}
What I don't like about this method is that I can pretty much pass any bound function in the PopupMenu constructor and it will be called. But that's not what I want, I want to enforce only a function with a specific signature.
I can also pass a lambda, yes. But let's try to solve it without lambdas.
Thank you all in advance for your help.
std::bind(&EditorWidget::editRow, editorWidget, item)
std::bind here is creating a functional object that takes a pointer to a member function EditorWidget::editRow, bound to an object editorWidget, using the parameter item. What you've done is actually fix the parameter to the function EditorWidget::editRow with the parameter item. So effectively you've created a function object that takes no argument (since you've fixed it), and returns void.
There's actually no need for the constructor of PopupMenu to have a second parameter of type RowItem*. You could change the constructor like so:
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction)
{
}
and then call your function object like this:
PopupMenu::execute(} {
_editRowFunction();
}
In your current code the parameter _item is not being used by the function object you pass into the constructor PopupMenu. It satisfies the compiler since _editRowFunction is of type std::function<void(RowItem*)>.
Here's a simple example to illustrate to the point:
#include <iostream>
#include <functional>
struct callable
{
callable(std::function<void(std::string)> fn) : mFn(fn)
{}
std::function<void(std::string)> mFn;
void Run() { mFn("world"); }
};
struct Foo {
void print(std::string msg)
{
std::cout << msg << '\n';
}
};
int main()
{
Foo f;
auto fn = std::bind(&Foo::print, &f, "hello");
fn();
callable c(fn);
c.Run(); //expecting "world" to be printed
}
You might expect the output to be:
hello
world
but actually it's:
hello
hello
Live demo.
What I could do is change the definition of the function object like this:
auto fn = std::bind(&Foo::print, &f, std::placeholders::_1); //uses a placeholder
and I get the expected output. You could do something similar without having to make many changes to your current implementation.

Is it possible to return a reference via an argument passed by reference?

I want to return a boolean or success/failure enum from the function and modify an argument by reference. However, I want to construct a reference in the calling function instead of copying the value.
I have some container (say 'example_q' of type std::queue). queue.front() will return a reference to the value stored in the queue. I can make a copy of that reference (example A) or I can take a reference of that reference (example B), allowing the value to stay in the queue but be utilized outside of it.
A)
int a = example_q.front();
B)
int& b = example_q.front();
Using this difference I could also return the queued value:
A)
int get_front()
{
int a = example_q.front();
return a;
}
B)
int& get_front()
{
return example_q.front();
}
Using option 'B' I can avoid unnecessary copies without moving the data out of the queue via std::move() semantics.
My question is, can I do 'B' via an argument passed by reference? Would I need to use std::move()/rvalues/&& somehow?
void get_front(int& int_ref)
{
// somehow don't copy the value into referenced int_ref, but construct
// a reference in the caller based on an input argument?
int_ref = example_q.front();
}
The problem this would solve is making API match other functions that modify reference arguments but return a success/failure value, ie:
if(q.get_front(referrence_magic_here))
{
...
}
I could reverse the order to get the desired result, IE:
int& get_front(bool& success)
{
...
}
But I'd rather keep the pattern of my API as well as being able to do it via a single line in the if() statement if possible.
Perhaps something like:
bool get_front(int&& int_rvalue)
{
...
int_rvalue = example_q.front();
...
return true_or_false;
}
void calling_func()
{
...
if(get_front(int& magical_ref))
{
... //use magical_ref here?
}
...
}
No, you can't do that.
Other than in its initialiser, a reference behaves like the thing it refers to. By passing it as a function argument, you "hide" the initialiser from the part that wants to do the assignment. So, the function has no access to the referencey behaviour of the thing.
You will have to use pointers if you want to do that:
void get_front(int*& int_ptr)
{
int_ptr = &example_q.front();
}
int* ptr = nullptr;
get_front(ptr);
// optional:
int& ref = *ptr;
(Ew!)
Option B was fine.
This code is invalid C++:
if(get_front(int& magical_ref))
You cannot declare a new variable as you're passing it to a function. And because a reference variable must be declared and initialized at the same time, it wouldn't be possible to have a reference be initialized by passing it to a function.
You could however, do this:
if(int &magical_ref = get_front()) {
But note that you'd be checking whether magical_ref is 0 or not, which is different from the condition you have in your example.
If your logic is as simple as comparing the int, you could do:
if (int& magical_ref = get_front(); magical_ref == 42)
You can return a std::tuple<int&, /* status condition */> and check the status. For example:
std::tuple<int&, bool> get_front() {
static int example = 0;
return {example, false};
}
...
// C++17's structured bindings + if statement with initializer
if (auto [ref, success] = get_front(); success) {
ref = 42;
}
Demo

c++ remove custom object from vector : std::remove_if': no matching overloaded function found

In my project there is a vector
std::vector<std::shared_ptr<MovingEntity>>gameObjects;
Which I want to delete elements from if they meet the criteria.
Method to delete elements:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(), beeToClose);
bees.erase(q);
}
Method beeToClose:
bool GameWorld::beeToClose( const MovingEntity & bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
if (bee.getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance())
{
return true;
}
return false;
}
When I try to compile the code I get some errors which I tried to understand:
'GameWorld::beeToClose': non-standard syntax; use '&' to create a
pointer
Not sure why this message is given
'std::remove_if': no matching overloaded function found
I did not declare beeToClose right?
'q': cannot be used before it is initialized SDLFramework
q is not initialized because:
std::remove_if(bees.begin(), bees.end(), beeToClose);
does not run correct?
How can I remove a std::shared_ptr correctly from a vector correctly when meeting some criteria?
The syntax for forming a pointer to member function is &ClassName::FunctionName. So you need &GameWorld::beeToClose for a pointer to the beeToClose member function. In your case, you should use a lambda from which you call that function
auto q = std::remove_if(bees.begin(), bees.end(),
[&](shared_ptr<MovingEntity> const& bee){ return beeToClose(bee); });
Also, you're using the wrong vector::erase overload, you want the one that erases a range of elements, not the one that erases a single element.
bees.erase(q, bees.end());
The vector contains std::shared_ptr<MovingEntity> elements, so beeToClose() needs to accept a const std::shared_ptr<MovingEntity> & parameter as input, not a const MovingEntity & parameter. Also, beeToClose() appears to be a non-static class method that accesses a non-static class member (m_beekeeper), so you can't just pass beeToClose() directly to std::remove_if() as it does not have access to the calling object's this pointer, but you can wrap it in a lambda to capture the this pointer.
Try this:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(),
[this](const const std::shared_ptr<MovingEntity> &bee) {
return this->beeToClose(bee);
}
);
bees.erase(q, bees.end());
}
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return (bee->getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance());
}
You might also consider moving the distance calculation into Beekeeper instead:
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return !keeper->isInCatchDistance(bee);
}
bool Beekeeper::isInCatchDistance(const std::shared_ptr<MovingEntity> &bee)
{
return (bee->getConstPosition().distanceTo(getPosition()) <= getCatchDistance());
}

remove_if: Predicate error when passing a function returning bool

I have this pre-defined function.
void attack(std::vector<GameObject*> objects, unsigned damage) {
for (GameObject* object : objects) {
object->takeDamage(damage);
auto isDead = object->isDead();
objects.erase(std::remove_if(objects.begin(),objects.end(),isDead), objects.end());
}
}
This is my isDead function
bool isDead() const {
if (destructed) {
std::cout << "memory error" << std::endl;
}
return life <= 0;
}
This is the error I keep getting. Have tried a lot of things, but not at all able to figure this one out. Any help appreciated!
error: expression cannot be used as a function
{ return bool(_M_pred(*__it)); }
isDead is a variable in the function. You can't use it as an argument to remove_if.
You can't use a regular member function as argument to std::remove_if either. Use a lambda function instead.
Don't erase objects from a container while you are iterating over it using a range for loop.
Change the argument to attack to be a reference. Otherwise, you will be removing objects from a copy, not the original container.
Here's an updated version of attack:
void attack(std::vector<GameObject*>& objects, unsigned damage)
{
for (GameObject* object : objects)
{
object->takeDamage(damage);
}
objects.erase(std::remove_if(objects.begin(),objects.end(), [](GameObject* object){return object->isDead();}), objects.end());
}
isDead() is a member function of one of your classes, which is exactly why it doesn't work: you did not supply this pointer (object instance) for it to be called on. Oh, and the predicate for remove_if must have exactly one argument of the type objects::value_type.
Do this instead:
objects.erase(std::remove_if(objects.begin(),objects.end(),[](GameObject* object){return object->isDead()), objects.end());

Handling functions with more than one output parameters

How do we handle more than one output parameters in C++.I am beginner in C++ and currently i am trying to write a function A which calls another function B of some other class,Function B consists of 6 parameters in total ,of which three are input parameters and the rest three are output parameters.How can i access all the three output parameters within my function A?I tried to do it in the following way...Can anyone help me to correct my code if i have gone wrong..?Please do help me friends..
class A ::functionA()
{
int in_a=1;
string in_b= "name";
int in_c=3;
int ot_a=0;
int ot_b=0;
string ot_s1=""
ClassB *classB();
classB = classB.functionB(in_a,in_b,in_c,ot_a,ot_b,ot_s1); //is this way correct?
ot_a= ? ;
ot_b=? ;
ot_s1=?
}
can i use something like ot_a=classB.ot_a ?Please help me...
You have got the basic syntax of C++ wrong. ClassB *classB(); does not create any object, it declares a function prototype of function classB which returns ClassB*. To create a object you should do ClassB b; and then use b as you have done. The output variables will be correctly filled up by the function if it is taking its parameter by reference.
For multiple return values, you got generally two choices:
return a struct containing your return values
pass the return values in per reference.
Both examples demonstrated:
// first approach, struct return
struct myReturns{
int int_return;
float float_return;
};
myReturns MyFunc(int param1, char* param2, ...){
// do some stuff with the parameters
myReturns ret;
ret.int_return = 42;
ret.float_return = 13.37f;
return ret;
}
// calling it:
myReturns ret = MyFunc(/*pass your parameters here*/);
int i = ret.int_return;
float f = ret.float_return;
// second approach, out parameters
void MyFunc(int inParam1, char* inParam2, int& outInt, float& outFloat){
// do some stuff with the parameters
outInt = 42;
outFloat = 13.37f;
}
// calling it:
int i;
float f;
MyFunc(/*your parameters here*/,i,f);
// i and f are now changed with the return values
As mentionned in Xeo's answer, you can use return structures or references.
There is another possibility, to use pointers.
Pointers allows you to do one thing : if the function you call can be used to compute multiple informations, but you don't want all of them, you can pass NULL as the value of the pointer so that the function knows it doesn't need to fill these informations.
Of course, the function you call needs to be designed that way, it's not automatic.
void f()
{
type1* p1 = new type1();
type2* p2 = NULL
g(p1, p2);
}
void g(type1* param1, type2* param2)
{
//Do some computation here
if (param1 != NULL)
{
//Do something here to fill param1
}
if (param2 != NULL)
{
//Do something here to fill param2
}
}
But as a general rule, it's better to use references when you can, and pointers when tou have to. If the function doesn't handle the case when a pointer passed to it is NULL, you will end with a crash. References can't be NULL, so they avoid this problem.
Answer is: references.
ClassB *classB();
classB = classB.functionB(in_a,in_b,in_c,ot_a,ot_b,ot_s1);
By looking . operator after classB, I assume that you are thinking classB is an object. No, it is not.
ClassB *classB();
The above statement says - classB() is a function that takes no parameters and return type is a reference to ClassB.
If you can change functionB() then use pointers as parameters. This way you can change the value inside functionB() and they will be changed directly in functionA().