Merge "De-cruft the libbcc compiler infrastructure."
diff --git a/include/bcc/Compiler.h b/include/bcc/Compiler.h
index 630be08..fabbadc 100644
--- a/include/bcc/Compiler.h
+++ b/include/bcc/Compiler.h
@@ -64,14 +64,7 @@
     kErrPrepareOutput,
     kPrepareCodeGenPass,
 
-    kErrHookBeforeAddLTOPasses,
-    kErrHookAfterAddLTOPasses,
-    kErrHookAfterExecuteLTOPasses,
-
-    kErrHookBeforeAddCodeGenPasses,
-    kErrHookAfterAddCodeGenPasses,
-    kErrHookBeforeExecuteCodeGenPasses,
-    kErrHookAfterExecuteCodeGenPasses,
+    kErrCustomPasses,
 
     kErrInvalidSource
   };
@@ -80,11 +73,14 @@
 
 private:
   llvm::TargetMachine *mTarget;
-  // LTO is enabled by default.
-  bool mEnableLTO;
+  // Optimization is enabled by default.
+  bool mEnableOpt;
 
-  enum ErrorCode runLTO(Script &pScript);
-  enum ErrorCode runCodeGen(Script &pScript, llvm::raw_ostream &pResult);
+  enum ErrorCode runPasses(Script &pScript, llvm::raw_ostream &pResult);
+
+  bool addCustomPasses(Script &pScript, llvm::PassManager &pPM);
+  bool addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM);
+  bool addExpandForEachPass(Script &pScript, llvm::PassManager &pPM);
 
 public:
   Compiler();
@@ -106,48 +102,10 @@
   const llvm::TargetMachine& getTargetMachine() const
   { return *mTarget; }
 
-  void enableLTO(bool pEnable = true)
-  { mEnableLTO = pEnable; }
+  void enableOpt(bool pEnable = true)
+  { mEnableOpt = pEnable; }
 
-  virtual ~Compiler();
-
-protected:
-  //===--------------------------------------------------------------------===//
-  // Plugin callbacks for sub-class.
-  //===--------------------------------------------------------------------===//
-  // Called before adding first pass to code-generation passes.
-  virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
-  { return true; }
-
-  // Called after adding last pass to code-generation passes.
-  virtual bool afterAddLTOPasses(Script &pScript, llvm::PassManager &pPM)
-  { return true; }
-
-  // Called before executing code-generation passes.
-  virtual bool beforeExecuteLTOPasses(Script &pScript,
-                                          llvm::PassManager &pPM)
-  { return true; }
-
-  // Called after executing code-generation passes.
-  virtual bool afterExecuteLTOPasses(Script &pScript)
-  { return true; }
-
-  // Called before adding first pass to code-generation passes.
-  virtual bool beforeAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
-  { return true; }
-
-  // Called after adding last pass to code-generation passes.
-  virtual bool afterAddCodeGenPasses(Script &pScript, llvm::PassManager &pPM)
-  { return true; }
-
-  // Called before executing code-generation passes.
-  virtual bool beforeExecuteCodeGenPasses(Script &pScript,
-                                          llvm::PassManager &pPM)
-  { return true; }
-
-  // Called after executing code-generation passes.
-  virtual bool afterExecuteCodeGenPasses(Script &pScript)
-  { return true; }
+  ~Compiler();
 };
 
 } // end namespace bcc
diff --git a/include/bcc/Renderscript/RSCompiler.h b/include/bcc/Renderscript/RSCompiler.h
deleted file mode 100644
index a46d558..0000000
--- a/include/bcc/Renderscript/RSCompiler.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_RS_COMPILER_H
-#define BCC_RS_COMPILER_H
-
-#include "bcc/Compiler.h"
-
-namespace bcc {
-
-class RSCompiler : public Compiler {
-private:
-  virtual bool beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM);
-  bool addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM);
-  bool addExpandForEachPass(Script &pScript, llvm::PassManager &pPM);
-};
-
-} // end namespace bcc
-
-#endif // BCC_RS_COMPILER_H
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index a2a68d1..3ad9e01 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -17,11 +17,11 @@
 #ifndef BCC_RS_COMPILER_DRIVER_H
 #define BCC_RS_COMPILER_DRIVER_H
 
+#include "bcc/Compiler.h"
 #include "bcc/ExecutionEngine/CompilerRTSymbolResolver.h"
 #include "bcc/ExecutionEngine/SymbolResolvers.h"
 #include "bcc/ExecutionEngine/SymbolResolverProxy.h"
 #include "bcc/Renderscript/RSInfo.h"
-#include "bcc/Renderscript/RSCompiler.h"
 #include "bcc/Renderscript/RSScript.h"
 
 namespace bcc {
@@ -39,7 +39,7 @@
 class RSCompilerDriver {
 private:
   CompilerConfig *mConfig;
-  RSCompiler mCompiler;
+  Compiler mCompiler;
 
   // Are we compiling under an RS debug context with additional checks?
   bool mDebugContext;
@@ -73,7 +73,7 @@
   RSCompilerDriver(bool pUseCompilerRT = true);
   ~RSCompilerDriver();
 
-  RSCompiler *getCompiler() {
+  Compiler *getCompiler() {
     return &mCompiler;
   }
 
diff --git a/lib/Core/Compiler.cpp b/lib/Core/Compiler.cpp
index c5890e2..4b4b4b7 100644
--- a/lib/Core/Compiler.cpp
+++ b/lib/Core/Compiler.cpp
@@ -28,11 +28,16 @@
 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
 #include <llvm/Transforms/Scalar.h>
 
+#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSExecutable.h"
+#include "bcc/Renderscript/RSScript.h"
+#include "bcc/Renderscript/RSTransforms.h"
 #include "bcc/Script.h"
 #include "bcc/Source.h"
 #include "bcc/Support/CompilerConfig.h"
 #include "bcc/Support/Log.h"
 #include "bcc/Support/OutputFile.h"
+#include "bcinfo/MetadataExtractor.h"
 
 #include <string>
 
@@ -62,20 +67,8 @@
     return "Failed to prepare file for output.";
   case kPrepareCodeGenPass:
     return "Failed to construct pass list for code-generation.";
-  case kErrHookBeforeAddLTOPasses:
-    return "Error occurred during beforeAddLTOPasses() in subclass.";
-  case kErrHookAfterAddLTOPasses:
-    return "Error occurred during afterAddLTOPasses() in subclass.";
-  case kErrHookAfterExecuteLTOPasses:
-    return "Error occurred during afterExecuteLTOPasses() in subclass.";
-  case kErrHookBeforeAddCodeGenPasses:
-    return "Error occurred during beforeAddCodeGenPasses() in subclass.";
-  case kErrHookAfterAddCodeGenPasses:
-    return "Error occurred during afterAddCodeGenPasses() in subclass.";
-  case kErrHookBeforeExecuteCodeGenPasses:
-    return "Error occurred during beforeExecuteCodeGenPasses() in subclass.";
-  case kErrHookAfterExecuteCodeGenPasses:
-    return "Error occurred during afterExecuteCodeGenPasses() in subclass.";
+  case kErrCustomPasses:
+    return "Error occurred while adding custom passes.";
   case kErrInvalidSource:
     return "Error loading input bitcode";
   }
@@ -89,12 +82,12 @@
 //===----------------------------------------------------------------------===//
 // Instance Methods
 //===----------------------------------------------------------------------===//
-Compiler::Compiler() : mTarget(nullptr), mEnableLTO(true) {
+Compiler::Compiler() : mTarget(nullptr), mEnableOpt(true) {
   return;
 }
 
 Compiler::Compiler(const CompilerConfig &pConfig) : mTarget(nullptr),
-                                                    mEnableLTO(true) {
+                                                    mEnableOpt(true) {
   const std::string &triple = pConfig.getTriple();
 
   enum ErrorCode err = config(pConfig);
@@ -123,7 +116,7 @@
 
   if (new_target == nullptr) {
     return ((mTarget != nullptr) ? kErrSwitchTargetMachine :
-                                kErrCreateTargetMachine);
+                                   kErrCreateTargetMachine);
   }
 
   // Replace the old TargetMachine.
@@ -146,98 +139,50 @@
   delete mTarget;
 }
 
-enum Compiler::ErrorCode Compiler::runLTO(Script &pScript) {
-  llvm::DataLayoutPass *data_layout_pass = nullptr;
-
+enum Compiler::ErrorCode Compiler::runPasses(Script &pScript,
+                                             llvm::raw_ostream &pResult) {
   // Pass manager for link-time optimization
-  llvm::PassManager lto_passes;
+  llvm::PassManager passes;
+
+  // Empty MCContext.
+  llvm::MCContext *mc_context = nullptr;
 
   // Prepare DataLayout target data from Module
-  data_layout_pass = new (std::nothrow) llvm::DataLayoutPass(*mTarget->getDataLayout());
+  llvm::DataLayoutPass *data_layout_pass =
+    new (std::nothrow) llvm::DataLayoutPass(*mTarget->getDataLayout());
+
   if (data_layout_pass == nullptr) {
     return kErrDataLayoutNoMemory;
   }
 
   // Add DataLayout to the pass manager.
-  lto_passes.add(data_layout_pass);
+  passes.add(data_layout_pass);
 
-  // Invoke "beforeAddLTOPasses" before adding the first pass.
-  if (!beforeAddLTOPasses(pScript, lto_passes)) {
-    return kErrHookBeforeAddLTOPasses;
+  // Add our custom passes.
+  if (!addCustomPasses(pScript, passes)) {
+    return kErrCustomPasses;
   }
 
   if (mTarget->getOptLevel() == llvm::CodeGenOpt::None) {
-    lto_passes.add(llvm::createGlobalOptimizerPass());
-    lto_passes.add(llvm::createConstantMergePass());
+    passes.add(llvm::createGlobalOptimizerPass());
+    passes.add(llvm::createConstantMergePass());
+
   } else {
     // FIXME: Figure out which passes should be executed.
     llvm::PassManagerBuilder Builder;
-    Builder.populateLTOPassManager(lto_passes, /*Internalize*/false,
-                                   /*RunInliner*/true);
-  }
-
-  // Invoke "afterAddLTOPasses" after pass manager finished its
-  // construction.
-  if (!afterAddLTOPasses(pScript, lto_passes)) {
-    return kErrHookAfterAddLTOPasses;
-  }
-
-  lto_passes.run(pScript.getSource().getModule());
-
-  // Invoke "afterExecuteLTOPasses" before returning.
-  if (!afterExecuteLTOPasses(pScript)) {
-    return kErrHookAfterExecuteLTOPasses;
-  }
-
-  return kSuccess;
-}
-
-enum Compiler::ErrorCode Compiler::runCodeGen(Script &pScript,
-                                              llvm::raw_ostream &pResult) {
-  llvm::DataLayoutPass *data_layout_pass;
-  llvm::MCContext *mc_context = nullptr;
-
-  // Create pass manager for MC code generation.
-  llvm::PassManager codegen_passes;
-
-  // Prepare DataLayout target data from Module
-  data_layout_pass = new (std::nothrow) llvm::DataLayoutPass(*mTarget->getDataLayout());
-  if (data_layout_pass == nullptr) {
-    return kErrDataLayoutNoMemory;
-  }
-
-  // Add DataLayout to the pass manager.
-  codegen_passes.add(data_layout_pass);
-
-  // Invokde "beforeAddCodeGenPasses" before adding the first pass.
-  if (!beforeAddCodeGenPasses(pScript, codegen_passes)) {
-    return kErrHookBeforeAddCodeGenPasses;
+    Builder.populateLTOPassManager(passes,
+                                   /*Internalize*/ false,
+                                   /*RunInliner*/  true);
   }
 
   // Add passes to the pass manager to emit machine code through MC layer.
-  if (mTarget->addPassesToEmitMC(codegen_passes, mc_context, pResult,
+  if (mTarget->addPassesToEmitMC(passes, mc_context, pResult,
                                  /* DisableVerify */false)) {
     return kPrepareCodeGenPass;
   }
 
-  // Invokde "afterAddCodeGenPasses" after pass manager finished its
-  // construction.
-  if (!afterAddCodeGenPasses(pScript, codegen_passes)) {
-    return kErrHookAfterAddCodeGenPasses;
-  }
-
-  // Invokde "beforeExecuteCodeGenPasses" before executing the passes.
-  if (!beforeExecuteCodeGenPasses(pScript, codegen_passes)) {
-    return kErrHookBeforeExecuteCodeGenPasses;
-  }
-
-  // Execute the pass.
-  codegen_passes.run(pScript.getSource().getModule());
-
-  // Invokde "afterExecuteCodeGenPasses" before returning.
-  if (!afterExecuteCodeGenPasses(pScript)) {
-    return kErrHookAfterExecuteCodeGenPasses;
-  }
+  // Execute the passes.
+  passes.run(pScript.getSource().getModule());
 
   return kSuccess;
 }
@@ -280,15 +225,12 @@
     }
   }
 
-  if (mEnableLTO && ((err = runLTO(pScript)) != kSuccess)) {
+  if ((err = runPasses(pScript, pResult)) != kSuccess) {
     return err;
   }
 
-  if (IRStream)
+  if (IRStream) {
     *IRStream << module;
-
-  if ((err = runCodeGen(pScript, pResult)) != kSuccess) {
-    return err;
   }
 
   return kSuccess;
@@ -316,3 +258,84 @@
 
   return err;
 }
+
+bool Compiler::addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM) {
+  // Add a pass to internalize the symbols that don't need to have global
+  // visibility.
+  RSScript &script = static_cast<RSScript &>(pScript);
+  llvm::Module &module = script.getSource().getModule();
+  bcinfo::MetadataExtractor me(&module);
+  if (!me.extract()) {
+    bccAssert(false && "Could not extract metadata for module!");
+    return false;
+  }
+
+  // The vector contains the symbols that should not be internalized.
+  std::vector<const char *> export_symbols;
+
+  // Special RS functions should always be global symbols.
+  const char **special_functions = RSExecutable::SpecialFunctionNames;
+  while (*special_functions != nullptr) {
+    export_symbols.push_back(*special_functions);
+    special_functions++;
+  }
+
+  // Visibility of symbols appeared in rs_export_var and rs_export_func should
+  // also be preserved.
+  size_t exportVarCount = me.getExportVarCount();
+  size_t exportFuncCount = me.getExportFuncCount();
+  size_t exportForEachCount = me.getExportForEachSignatureCount();
+  const char **exportVarNameList = me.getExportVarNameList();
+  const char **exportFuncNameList = me.getExportFuncNameList();
+  const char **exportForEachNameList = me.getExportForEachNameList();
+  size_t i;
+
+  for (i = 0; i < exportVarCount; ++i) {
+    export_symbols.push_back(exportVarNameList[i]);
+  }
+
+  for (i = 0; i < exportFuncCount; ++i) {
+    export_symbols.push_back(exportFuncNameList[i]);
+  }
+
+  // Expanded foreach functions should not be internalized, too.
+  // expanded_foreach_funcs keeps the .expand version of the kernel names
+  // around until createInternalizePass() is finished making its own
+  // copy of the visible symbols.
+  std::vector<std::string> expanded_foreach_funcs;
+  for (i = 0; i < exportForEachCount; ++i) {
+    expanded_foreach_funcs.push_back(
+        std::string(exportForEachNameList[i]) + ".expand");
+  }
+
+  for (i = 0; i < exportForEachCount; i++) {
+      export_symbols.push_back(expanded_foreach_funcs[i].c_str());
+  }
+
+  pPM.add(llvm::createInternalizePass(export_symbols));
+
+  return true;
+}
+
+bool Compiler::addExpandForEachPass(Script &pScript, llvm::PassManager &pPM) {
+  // Script passed to RSCompiler must be a RSScript.
+  RSScript &script = static_cast<RSScript &>(pScript);
+
+  // Expand ForEach on CPU path to reduce launch overhead.
+  bool pEnableStepOpt = true;
+  pPM.add(createRSForEachExpandPass(pEnableStepOpt));
+  if (script.getEmbedInfo())
+    pPM.add(createRSEmbedInfoPass());
+
+  return true;
+}
+
+bool Compiler::addCustomPasses(Script &pScript, llvm::PassManager &pPM) {
+  if (!addExpandForEachPass(pScript, pPM))
+    return false;
+
+  if (!addInternalizeSymbolsPass(pScript, pPM))
+    return false;
+
+  return true;
+}
diff --git a/lib/Renderscript/Android.mk b/lib/Renderscript/Android.mk
index cac894a..133966e 100644
--- a/lib/Renderscript/Android.mk
+++ b/lib/Renderscript/Android.mk
@@ -22,7 +22,6 @@
 #=====================================================================
 
 libbcc_renderscript_SRC_FILES := \
-  RSCompiler.cpp \
   RSCompilerDriver.cpp \
   RSEmbedInfo.cpp \
   RSExecutable.cpp \
diff --git a/lib/Renderscript/RSCompiler.cpp b/lib/Renderscript/RSCompiler.cpp
deleted file mode 100644
index dc5ba6a..0000000
--- a/lib/Renderscript/RSCompiler.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bcc/Renderscript/RSCompiler.h"
-
-#include <llvm/IR/Module.h>
-#include <llvm/PassManager.h>
-#include <llvm/Transforms/IPO.h>
-
-#include "bcc/Assert.h"
-#include "bcc/Renderscript/RSExecutable.h"
-#include "bcc/Renderscript/RSScript.h"
-#include "bcc/Renderscript/RSTransforms.h"
-#include "bcc/Source.h"
-#include "bcc/Support/Log.h"
-#include "bcinfo/MetadataExtractor.h"
-
-using namespace bcc;
-
-bool RSCompiler::addInternalizeSymbolsPass(Script &pScript, llvm::PassManager &pPM) {
-  // Add a pass to internalize the symbols that don't need to have global
-  // visibility.
-  RSScript &script = static_cast<RSScript &>(pScript);
-  llvm::Module &module = script.getSource().getModule();
-  bcinfo::MetadataExtractor me(&module);
-  if (!me.extract()) {
-    bccAssert(false && "Could not extract metadata for module!");
-    return false;
-  }
-
-  // The vector contains the symbols that should not be internalized.
-  std::vector<const char *> export_symbols;
-
-  // Special RS functions should always be global symbols.
-  const char **special_functions = RSExecutable::SpecialFunctionNames;
-  while (*special_functions != nullptr) {
-    export_symbols.push_back(*special_functions);
-    special_functions++;
-  }
-
-  // Visibility of symbols appeared in rs_export_var and rs_export_func should
-  // also be preserved.
-  size_t exportVarCount = me.getExportVarCount();
-  size_t exportFuncCount = me.getExportFuncCount();
-  size_t exportForEachCount = me.getExportForEachSignatureCount();
-  const char **exportVarNameList = me.getExportVarNameList();
-  const char **exportFuncNameList = me.getExportFuncNameList();
-  const char **exportForEachNameList = me.getExportForEachNameList();
-  size_t i;
-
-  for (i = 0; i < exportVarCount; ++i) {
-    export_symbols.push_back(exportVarNameList[i]);
-  }
-
-  for (i = 0; i < exportFuncCount; ++i) {
-    export_symbols.push_back(exportFuncNameList[i]);
-  }
-
-  // Expanded foreach functions should not be internalized, too.
-  // expanded_foreach_funcs keeps the .expand version of the kernel names
-  // around until createInternalizePass() is finished making its own
-  // copy of the visible symbols.
-  std::vector<std::string> expanded_foreach_funcs;
-  for (i = 0; i < exportForEachCount; ++i) {
-    expanded_foreach_funcs.push_back(
-        std::string(exportForEachNameList[i]) + ".expand");
-  }
-
-  for (i = 0; i < exportForEachCount; i++) {
-      export_symbols.push_back(expanded_foreach_funcs[i].c_str());
-  }
-
-  pPM.add(llvm::createInternalizePass(export_symbols));
-
-  return true;
-}
-
-bool RSCompiler::addExpandForEachPass(Script &pScript, llvm::PassManager &pPM) {
-  // Script passed to RSCompiler must be a RSScript.
-  RSScript &script = static_cast<RSScript &>(pScript);
-
-  // Expand ForEach on CPU path to reduce launch overhead.
-  bool pEnableStepOpt = true;
-  pPM.add(createRSForEachExpandPass(pEnableStepOpt));
-  if (script.getEmbedInfo())
-    pPM.add(createRSEmbedInfoPass());
-
-  return true;
-}
-
-bool RSCompiler::beforeAddLTOPasses(Script &pScript, llvm::PassManager &pPM) {
-  if (!addExpandForEachPass(pScript, pPM))
-    return false;
-
-  if (!addInternalizeSymbolsPass(pScript, pPM))
-    return false;
-
-  return true;
-}
diff --git a/tools/bcc/Main.cpp b/tools/bcc/Main.cpp
index 6b9b13d..9c6ed45 100644
--- a/tools/bcc/Main.cpp
+++ b/tools/bcc/Main.cpp
@@ -116,7 +116,7 @@
 
 static inline
 bool ConfigCompiler(RSCompilerDriver &pRSCD) {
-  RSCompiler *RSC = pRSCD.getCompiler();
+  Compiler *RSC = pRSCD.getCompiler();
   CompilerConfig *config = nullptr;
 
   config = new (std::nothrow) CompilerConfig(OptTargetTriple);
diff --git a/tools/bcc_compat/Main.cpp b/tools/bcc_compat/Main.cpp
index f7875e8..6593d9a 100644
--- a/tools/bcc_compat/Main.cpp
+++ b/tools/bcc_compat/Main.cpp
@@ -151,7 +151,7 @@
 
 static inline
 bool ConfigCompiler(RSCompilerDriver &pCompilerDriver) {
-  RSCompiler *compiler = pCompilerDriver.getCompiler();
+  Compiler *compiler = pCompilerDriver.getCompiler();
   CompilerConfig *config = nullptr;
 
   config = new (std::nothrow) CompilerConfig(OptTargetTriple);