[PM] Add pass run listeners to the pass manager.

This commit provides the necessary C/C++ APIs and infastructure to enable fine-
grain progress report and safe suspension points after each pass in the pass
manager.

Clients can provide a callback function to the pass manager to call after each
pass. This can be used in a variety of ways (progress report, dumping of IR
between passes, safe suspension of threads, etc).

The run listener list is maintained in the LLVMContext, which allows a multi-
threaded client to be only informed for it's own thread. This of course assumes
that the client created a LLVMContext for each thread.

This fixes <rdar://problem/16728690>

llvm-svn: 207430
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index be5727b..a843b9f 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -27,6 +27,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
 #include "llvm/PassManager.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -43,6 +44,21 @@
 
 #define DEBUG_TYPE "ir"
 
+namespace {
+struct LLVMPassRunListener : PassRunListener {
+  LLVMPassRunListenerHandlerTy Callback;
+
+  LLVMPassRunListener(LLVMContext *Context, LLVMPassRunListenerHandlerTy Fn)
+    : PassRunListener(Context), Callback(Fn) {}
+  void passRun(LLVMContext *C, Pass *P, Module *M, Function *F,
+               BasicBlock *BB) override {
+    Callback(wrap(C), wrap(P), wrap(M), wrap(F), wrap(BB));
+  }
+};
+// Create wrappers for C Binding types (see CBindingWrapping.h).
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassRunListener, LLVMPassRunListenerRef)
+} // end anonymous namespace
+
 void llvm::initializeCore(PassRegistry &Registry) {
   initializeDominatorTreeWrapperPassPass(Registry);
   initializePrintModulePassWrapperPass(Registry);
@@ -133,7 +149,15 @@
     return severity;
 }
 
+LLVMPassRunListenerRef LLVMAddPassRunListener(LLVMContextRef Context,
+                                              LLVMPassRunListenerHandlerTy Fn) {
+  return wrap(new LLVMPassRunListener(unwrap(Context), Fn));
+}
 
+void LLVMRemovePassRunListener(LLVMContextRef Context,
+                               LLVMPassRunListenerRef Listener) {
+  unwrap(Context)->removeRunListener(unwrap(Listener));
+}
 
 
 /*===-- Operations on modules ---------------------------------------------===*/
@@ -2646,6 +2670,12 @@
   delete unwrap(MemBuf);
 }
 
+/*===-- Pass  -------------------------------------------------------------===*/
+
+const char *LLVMGetPassName(LLVMPassRef P) {
+  return unwrap(P)->getPassName();
+}
+
 /*===-- Pass Registry -----------------------------------------------------===*/
 
 LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void) {