[llvm-commits] CVS: llvm/include/llvm/Support/Debug.h

Bill Wendling isanbard at gmail.com
Thu Nov 16 19:38:12 PST 2006


On Nov 16, 2006, at 6:25 PM, Reid Spencer wrote:
> On Thu, 2006-11-16 at 17:44 -0800, Bill Wendling wrote:
>> Basically, this is to get rid of static c'tor/d'tors scattered all
>> over the source tree. (You get them whenever you #include  
>> <iostream>.)
>> A smart compiler should be able to remove all of the empty functions
>> because they don't have any side-effects.
>
Hi Reid,

> I understand the motivation for the change and I commend it, but I'm
> concerned about getting it right. You're assuming a few things: a) the
> compiler is smart enough to get rid of calls that have no side  
> effects,
> b) the compiler knows how to determine if a function has no side  
> effects
> without help (operator<< isn't marked "pure"), and c) that there  
> aren't
> any side effects.  c) can probably be proven by your iostream
> implementation but a) and b) are a little tougher.
>
Of course, LLVM is self-hosted, so it should be smart enough to  
handle it. :-)

> Can we build an optimized, with symbols (-g -O2) version of one of  
> these
> modules and see if those symbols are getting removed ?  If so, I'm  
> fine
> with it. If not, we need a new strategy.
>
I hope I did this correctly. Anyway, here are the files:

t.h:

#include <ostream>

class llvm_ostream {
   std::ostream* Stream;
public:
   llvm_ostream() : Stream(0) {}
   llvm_ostream(std::ostream& OStream) : Stream(&OStream) {}

   template <typename Ty>
   llvm_ostream& operator << (const Ty& Thing) {
#ifndef NDEBUG
     if (Stream) *Stream << Thing;
#endif
     return *this;
   }
};

/// getErrorOutputStream - Returns the error output stream  
(std::cerr). This
/// places the std::c* I/O streams into one .cpp file and relieves  
the whole
/// program from having to have hundreds of static c'tor/d'tors for  
them.
///
llvm_ostream getErrorOutputStream(const char *DebugType);

#ifdef NDEBUG
#define DOUT llvm_ostream()
#else
#define DOUT getErrorOutputStream(DEBUG_TYPE)
#endif

t.cpp:

#define DEBUG_TYPE "experiment"
#include "t.h"

int main()
{
   DOUT << "Hello world\n";
}


foo.cpp:

#include "t.h"
#include <iostream>

llvm_ostream getErrorOutputStream(const char *DebugType) {
   if (DebugType)
     return llvm_ostream(std::cerr);
   else
     return llvm_ostream();
}


Compiled with -DNDEBUG -g -O2 gives:

$ nm -A foo.o
foo.o: 00000170 s EH_frame1
foo.o: 00000160 s __GLOBAL__I__Z20getErrorOutputStreamPKc
foo.o: 00000000 a __GLOBAL__I__Z20getErrorOutputStreamPKc.eh
foo.o: 00000000 T __Z20getErrorOutputStreamPKc
foo.o: 00000000 A __Z20getErrorOutputStreamPKc.eh
foo.o: 000000d0 s __Z41__static_initialization_and_destruction_0ii
foo.o: 0000018c s __Z41__static_initialization_and_destruction_0ii.eh
foo.o:          U __ZNSt8ios_base4InitC1Ev
foo.o:          U __ZNSt8ios_base4InitD1Ev
foo.o:          U __ZSt4cerr
foo.o: 000001d0 b __ZSt8__ioinit
foo.o:          U ___cxa_atexit
foo.o:          U ___dso_handle
foo.o:          U ___gxx_personality_v0
foo.o: 00000040 t ___tcf_0
foo.o: 00000000 a ___tcf_0.eh
foo.o:          U dyld_stub_binding_helper
$ nm -A t.o
t.o: 00000000 T _main
t.o: 00000000 A _main.eh

Compiling with -g -O2 gives:

$ nm -A foo.o
foo.o: 00000170 s EH_frame1
foo.o: 00000160 s __GLOBAL__I__Z20getErrorOutputStreamPKc
foo.o: 00000000 a __GLOBAL__I__Z20getErrorOutputStreamPKc.eh
foo.o: 00000000 T __Z20getErrorOutputStreamPKc
foo.o: 00000000 A __Z20getErrorOutputStreamPKc.eh
foo.o: 000000d0 s __Z41__static_initialization_and_destruction_0ii
foo.o: 0000018c s __Z41__static_initialization_and_destruction_0ii.eh
foo.o:          U __ZNSt8ios_base4InitC1Ev
foo.o:          U __ZNSt8ios_base4InitD1Ev
foo.o:          U __ZSt4cerr
foo.o: 000001d0 b __ZSt8__ioinit
foo.o:          U ___cxa_atexit
foo.o:          U ___dso_handle
foo.o:          U ___gxx_personality_v0
foo.o: 00000040 t ___tcf_0
foo.o: 00000000 a ___tcf_0.eh
foo.o:          U dyld_stub_binding_helper
$ nm -A t.o
t.o: 000000bc s EH_frame1
t.o:          U __Z20getErrorOutputStreamPKc
t.o:          U __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
t.o:          U ___gxx_personality_v0
t.o: 00000000 T _main
t.o: 000000d8 S _main.eh
t.o:          U dyld_stub_binding_helper

So it seems like gcc is doing the right thing, I suppose. I'm going  
to give it a try with the LLVM source in the CodeGen directory.

-bw




More information about the llvm-commits mailing list