changeset 1502:2292878925f4

Add an `llvm::OStream` workalike class for use with `Logger::cout()`, with the crucial difference being special handling of `llvm::Type`s so they get printed by name rather than printing their full representation (which can be positively *huge*). This allows re-enabling some logger calls that were disabled due to extreme verbosity.
author Frits van Bommel <fvbommel wxs.nl>
date Tue, 16 Jun 2009 19:31:10 +0200
parents 8b9f236dd051
children cc5fee7836dc
files gen/abi-x86-64.cpp gen/abi.cpp gen/asmstmt.cpp gen/classes.cpp gen/functions.cpp gen/linker.cpp gen/logger.cpp gen/logger.h gen/toobj.cpp ir/irtypeclass.cpp ir/irtypestruct.cpp
diffstat 11 files changed, 93 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/gen/abi-x86-64.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/abi-x86-64.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -701,11 +701,8 @@
             if (ty->ty == Tstruct)
                 fixup_D(arg);
             
-#if 0
-            // These can get pretty large...
             if (Logger::enabled())
                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
-#endif
         }
         
     } else {
@@ -735,10 +732,8 @@
             Type* ty = arg.type->toBasetype();
             
             fixup(arg);
-#if 0
             if (Logger::enabled())
                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
-#endif
         }
     }
 }
--- a/gen/abi.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/abi.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -385,10 +385,8 @@
             if (ty->ty == Tstruct)
                 fixup(arg);
 
-#if 0
             if (Logger::enabled())
                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
-#endif
         }
     }
 };
--- a/gen/asmstmt.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/asmstmt.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -721,7 +721,7 @@
         Logger::cout() << "Arguments:" << '\n';
         Logger::indent();
         for (std::vector<LLValue*>::iterator b = args.begin(), i = b, e = args.end(); i != e; ++i) {
-            llvm::OStream cout = Logger::cout();
+            Stream cout = Logger::cout();
             cout << '$' << (i - b) << " ==> " << **i;
             if (!llvm::isa<llvm::Instruction>(*i) && !llvm::isa<LLGlobalValue>(*i))
                 cout << '\n';
--- a/gen/classes.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/classes.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -491,9 +491,7 @@
     {
         Logger::cout() << "src2: " << *src << '\n';
         Logger::cout() << "index: " << field->index << '\n';
-#if 0
         Logger::cout() << "srctype: " << *src->getType() << '\n';
-#endif
     }
 #endif
     LLValue* val = DtoGEPi(src, 0, field->index);
--- a/gen/functions.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/functions.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -194,9 +194,7 @@
 
     llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
 
-#if 0
     Logger::cout() << "Final function type: " << *functype << "\n";
-#endif
 
     return functype;
 }
--- a/gen/linker.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/linker.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -329,7 +329,7 @@
 
     Logger::println("Linking with: ");
     std::vector<const char*>::const_iterator I = args.begin(), E = args.end(); 
-    llvm::OStream logstr = Logger::cout();
+    Stream logstr = Logger::cout();
     for (; I != E; ++I)
         if (*I)
             logstr << "'" << *I << "'" << " ";
--- a/gen/logger.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/logger.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -4,11 +4,34 @@
 #include <cstdlib>
 #include <fstream>
 #include <string>
+#include <iostream>
 
 #include "mars.h"
 
 #include "llvm/Support/CommandLine.h"
+
+#include "llvm/GlobalValue.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Assembly/Writer.h"
+
 #include "gen/logger.h"
+#include "gen/irstate.h"
+
+void Stream::writeType(std::ostream& OS, const llvm::Type& Ty) {
+    llvm::raw_os_ostream raw(OS);
+    llvm::WriteTypeSymbolic(raw, &Ty, gIR->module);
+}
+
+void Stream::writeValue(std::ostream& OS, const llvm::Value& V) {
+    // Constants don't always get their types pretty-printed.
+    // (Only treat non-global constants like this, so that e.g. global variables
+    // still get their initializers printed)
+    if (llvm::isa<llvm::Constant>(V) && !llvm::isa<llvm::GlobalValue>(V))
+        llvm::WriteAsOperand(OS, &V, true, gIR->module);
+    else
+        OS << V;
+}
 
 namespace Logger
 {
@@ -31,10 +54,10 @@
             indent_str.resize(indent_str.size()-2);
         }
     }
-    llvm::OStream cout()
+    Stream cout()
     {
         if (_enabled)
-            return llvm::cout << indent_str;
+            return std::cout << indent_str;
         else
             return 0;
     }
--- a/gen/logger.h	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/logger.h	Tue Jun 16 19:31:10 2009 +0200
@@ -1,7 +1,12 @@
 #ifndef _llvmd_gen_logger_h_
 #define _llvmd_gen_logger_h_
 
-#include "llvm/Support/Streams.h"
+#include <iosfwd>
+
+namespace llvm {
+    class Type;
+    class Value;
+}
 
 #ifndef IS_PRINTF
 # ifdef __GNUC__
@@ -13,11 +18,69 @@
 
 struct Loc;
 
+class Stream {
+    std::ostream* OS;
+    
+public:
+    Stream() : OS(0) {}
+    Stream(std::ostream* S) : OS(S) {}
+    Stream(std::ostream& S) : OS(&S) {}
+    
+    Stream operator << (std::ios_base &(*Func)(std::ios_base&)) {
+      if (OS) *OS << Func;
+      return *this;
+    }
+    
+    Stream operator << (std::ostream &(*Func)(std::ostream&)) {
+      if (OS) *OS << Func;
+      return *this;
+    }
+    
+    template<typename Ty>
+    Stream& operator << (const Ty& Thing) {
+        if (OS)
+            Writer<Ty, sizeof(sfinae_bait(Thing))>::write(*OS, Thing);
+        return *this;
+    }
+    
+private:
+    // Implementation details to treat llvm::Value, llvm::Type and their
+    // subclasses specially (to pretty-print types).
+    
+    static void writeType(std::ostream& OS, const llvm::Type& Ty);
+    static void writeValue(std::ostream& OS, const llvm::Value& Ty);
+    
+    template<typename Ty, int N> friend struct Writer;
+    // error: function template partial specialization is not allowed
+    // So I guess type partial specialization + member function will have to do...
+    template<typename Ty, int N>
+    struct Writer {
+        static void write(std::ostream& OS, const Ty& Thing) {
+            OS << Thing;
+        }
+    };
+    
+    template<typename Ty>
+    struct Writer<Ty, 1> {
+        static void write(std::ostream& OS, const llvm::Type& Thing) {
+            Stream::writeType(OS, Thing);
+        }
+        static void write(std::ostream& OS, const llvm::Value& Thing) {
+            Stream::writeValue(OS, Thing);
+        }
+    };
+    
+    // NOT IMPLEMENTED
+    char sfinae_bait(const llvm::Type&);
+    char sfinae_bait(const llvm::Value&);
+    short sfinae_bait(...);
+};
+
 namespace Logger
 {
     void indent();
     void undent();
-    llvm::OStream cout();
+    Stream cout();
     void println(const char* fmt, ...) IS_PRINTF(1);
     void print(const char* fmt, ...) IS_PRINTF(1);
     void enable();
--- a/gen/toobj.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/gen/toobj.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -385,7 +385,7 @@
     if (Logger::enabled()) {
         Logger::println("Assembling with: ");
         std::vector<const char*>::const_iterator I = Args.begin(), E = Args.end();
-        std::ostream& logstr = *Logger::cout().stream();
+        Stream logstr = Logger::cout();
         for (; I != E; ++I)
             if (*I)
                 logstr << "'" << *I << "'" << " ";
--- a/ir/irtypeclass.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/ir/irtypeclass.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -281,9 +281,7 @@
     name.append(".__vtbl");
     Type::sir->getState()->module->addTypeName(name, vtbl_pa.get());
 
-#if 0
     IF_LOG Logger::cout() << "class type: " << *pa.get() << std::endl;
-#endif
 
     return get();
 }
--- a/ir/irtypestruct.cpp	Tue Jun 16 15:37:40 2009 +0200
+++ b/ir/irtypestruct.cpp	Tue Jun 16 19:31:10 2009 +0200
@@ -227,9 +227,7 @@
     // name types
     Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get());
 
-#if 0
     IF_LOG Logger::cout() << "final struct type: " << *pa.get() << std::endl;
-#endif
 
     return pa.get();
 }