8

I have a function

void X(Object o)
{
 ....
}

When I compile it, I see, that clang changes its signature to

void X(Object* o)

It is inconvenient, because I use this function from some llvm IR code directly. How to forbid it from doing this optimization?

Edit: Minimal working example:

#include <stdio.h>

class Object
{
public:
    Object();
    ~Object();
    int* pointer;
};

void Function(Object o)
{
    o.pointer = 0;
}

int main()
{
    Object a;
    Function(a);
    return 0;
}

By the following command line:

clang++ tst.cpp -emit-llvm -O0 tst.cpp -S -std=c++11

The Function is translated into:

define void @_Z8Function6Object(%class.Object* %o) nounwind uwtable {
  %1 = getelementptr inbounds %class.Object* %o, i32 0, i32 0
  store i32* null, i32** %1, align 8
  ret void
}
Ali
  • 56,466
  • 29
  • 168
  • 265
Necto
  • 2,594
  • 1
  • 20
  • 45

1 Answers1

2

You need to add the option -mdisable-fp-elim

Disable frame pointer elimination optimization.

Here where i find this option : clang option

And here i well explanation of why clang do this : understand option 'omit frame pointer'

*Edit: *

After some inspection i have found this :

  • Your object is correctly pass by copy after compilling :

example:

#include <stdio.h>
#include <iostream>

class Object
{
public:
    std::string test;
    Object() {
    this->test = "I'm an object";
    std::cout << "Object created" << std::endl;
    }
    Object(Object &o) {
    this->test = "I'm a object copy";
    std::cout << "Object copy created" << std::endl;    
}
    ~Object() {
}
    int* pointer;
};

void Function(Object o)
{
    o.pointer = 0;
    std::cout << o.test << std::endl;
}

int main()
{
    Object a;
    Function(a);
    std::cout << a.test << std::endl;
    return 0;
}

output:

Object created

Object copy created

I'm a object copy

I'm an object

  • Second point:

you can see just after the function prototype

; Function Attrs: uwtable
define void @_Z8Function6Object(%class.Object* %o) #3 {
  %1 = getelementptr inbounds %class.Object* %o, i32 0, i32 1 // Get 
  store i32* null, i32** %1, align 8

That the function get the copy of the object. You can see in the main the copy of the object

So your code seems to work well in fact ;)

Community
  • 1
  • 1
Vink
  • 1,267
  • 9
  • 13
  • Didn't work for me. `clang: warning: argument unused during compilation: '-mdisable-fp-elim'` See The working example, added above – Necto Jul 01 '14 at 14:00
  • isn't clang++ compatible with gcc in its calling convention? `-fomit-frame-pointer`would be the gcc version and `-fno-omit-frame-pointer` to disable. – Alexander Oh Jul 01 '14 at 14:15
  • @Vink, That's right. The produced code is correct. But it is just one unit. Other object files assume the function to take a value, not a pointer, so they will not work. That's the point. – Necto Jul 01 '14 at 16:09
  • My point was : it looks like it's the way that clang works, because it play with the stack to passe object because object are memory area and it is the way that all clang and gcc works (may be not clear xD) – Vink Jul 01 '14 at 16:13
  • But isn't it slow - extra dereferencing (load) for each argument usage? – Necto Jul 02 '14 at 06:28
  • You create a copy, so the compiler have two choice : pass a pointer to the initial object then create a copy this object, but it not know how many time you will can this function (maybe many stack allocation/unalloc) or make the copy before and maybe reuse it. Plus for just one call, the necessary operation are the same for a copy before or in the function called. A last point : by making the allocation before the compiler can make one allocation request than many little. – Vink Jul 02 '14 at 06:37