Enhance diagnostic options.

- Support -m32/-m64 for non-cpp, if eng build.

- Add -ast-print option.

- Add options -debug, -print-before-all, -print-after-all (passthrough to LLVM).

Change-Id: I609750bd49a624d74f91666ef3f8c77ef711ff32
diff --git a/Android.mk b/Android.mk
index 55f35e7..e1d1bd1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,7 +33,7 @@
 
 local_cflags_for_slang := -Wall -Werror -std=c++11
 ifeq ($(TARGET_BUILD_VARIANT),eng)
-local_cflags_for_slang += -O0
+local_cflags_for_slang += -O0 -D__ENABLE_INTERNAL_OPTIONS
 else
 ifeq ($(TARGET_BUILD_VARIANT),userdebug)
 else
diff --git a/RSCCOptions.td b/RSCCOptions.td
index 96cdaa8..032029b 100644
--- a/RSCCOptions.td
+++ b/RSCCOptions.td
@@ -60,8 +60,8 @@
   HelpText<"Build ASTs then convert to LLVM, but emit nothing">;
 }
 
-def m32 : Flag<["-"], "m32">, HelpText<"Emit 32-bit C++ code">;
-def m64 : Flag<["-"], "m64">, HelpText<"Emit 64-bit C++ code">;
+def m32 : Flag<["-"], "m32">, HelpText<"Emit 32-bit code (only for C++, unless eng build)">;
+def m64 : Flag<["-"], "m64">, HelpText<"Emit 64-bit code (only for C++, unless eng build)">;
 
 def emit_g : Flag<["-"], "g">,
   HelpText<"Emit LLVM Debug Metadata">;
@@ -123,6 +123,21 @@
   HelpText<"Reflect C++ classes">;
 
 //===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+def ast_print : Flag<["-"], "ast-print">,
+  HelpText<"Print clang AST prior to llvm IR generation">;
+
+def debug : Flag<["-"], "debug">,
+  HelpText<"Enable debug output">;
+
+def print_after_all : Flag<["-"], "print-after-all">,
+  HelpText<"Print llvm IR after each pass">;
+def print_before_all : Flag<["-"], "print-before-all">,
+  HelpText<"Print llvm IR before each pass">;
+
+//===----------------------------------------------------------------------===//
 // Misc Options
 //===----------------------------------------------------------------------===//
 
diff --git a/rs_cc_options.cpp b/rs_cc_options.cpp
index 94d1453..2779c1c 100644
--- a/rs_cc_options.cpp
+++ b/rs_cc_options.cpp
@@ -222,11 +222,22 @@
       }
     }
   } else if (lastBitwidthArg) {
-    // -m32/-m64 are forbidden for non-C++ reflection paths.
-    DiagEngine.Report(
-        DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                   "cannot use -m32/-m64 without specifying "
-                                   "C++ reflection (-reflect-c++)"));
+      // -m32/-m64 are forbidden for non-C++ reflection paths for non-eng builds
+      // (they would make it too easy for a developer to accidentally create and
+      // release an APK that has 32-bit or 64-bit bitcode but not both).
+#ifdef __ENABLE_INTERNAL_OPTIONS
+      if (lastBitwidthArg->getOption().matches(OPT_m32)) {
+        Opts.mBitWidth = 32;
+      } else {
+        Opts.mBitWidth = 64;
+      }
+      Opts.mEmit3264 = false;
+#else
+      DiagEngine.Report(
+          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
+                                     "cannot use -m32/-m64 without specifying "
+                                     "C++ reflection (-reflect-c++)"));
+#endif
   }
 
   Opts.mDependencyOutputDir =
@@ -237,6 +248,25 @@
   Opts.mShowVersion = Args->hasArg(OPT_version);
   Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
   Opts.mVerbose = Args->hasArg(OPT_verbose);
+  Opts.mASTPrint = Args->hasArg(OPT_ast_print);
+
+  // Delegate options
+
+  std::vector<std::string> DelegatedStrings;
+  for (int Opt : std::vector<unsigned>{OPT_debug, OPT_print_after_all, OPT_print_before_all}) {
+    if (Args->hasArg(Opt)) {
+      // TODO: Don't assume that the option begins with "-"; determine this programmatically instead.
+      DelegatedStrings.push_back(std::string("-") + std::string(OptParser->getOptionName(Opt)));
+      slangAssert(OptParser->getOptionKind(Opt) == llvm::opt::Option::FlagClass);
+    }
+  }
+  if (DelegatedStrings.size()) {
+    std::vector<const char *> DelegatedCStrs;
+    DelegatedCStrs.push_back(*ArgVector.data()); // program name
+    std::for_each(DelegatedStrings.cbegin(), DelegatedStrings.cend(),
+                  [&DelegatedCStrs](const std::string &String) { DelegatedCStrs.push_back(String.c_str()); });
+    llvm::cl::ParseCommandLineOptions(DelegatedCStrs.size(), DelegatedCStrs.data());
+  }
 
   // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.
 
@@ -253,11 +283,10 @@
     Opts.mTargetAPI = UINT_MAX;
   }
 
-  Opts.mEmit3264 =
-      (Opts.mTargetAPI >= 21) && (Opts.mBitcodeStorage != BCST_CPP_CODE);
-  if (Opts.mEmit3264) {
+  if ((Opts.mTargetAPI < 21) || (Opts.mBitcodeStorage == BCST_CPP_CODE))
+    Opts.mEmit3264 = false;
+  if (Opts.mEmit3264)
     Opts.mBitcodeStorage = BCST_JAVA_CODE;
-  }
 
   if (DiagEngine.hasErrorOccurred()) {
     llvm::errs() << DiagsBuffer.str();
diff --git a/rs_cc_options.h b/rs_cc_options.h
index e45dae0..58503d7 100644
--- a/rs_cc_options.h
+++ b/rs_cc_options.h
@@ -98,6 +98,9 @@
   // Display verbose information about the compilation on stdout.
   bool mVerbose;
 
+  // Display AST.
+  bool mASTPrint;
+
   // Emit both 32-bit and 64-bit bitcode (embedded in the reflected sources).
   bool mEmit3264;
 
@@ -112,7 +115,8 @@
     mDebugEmission = 0;
     mOptimizationLevel = llvm::CodeGenOpt::Aggressive;
     mVerbose = false;
-    mEmit3264 = false;
+    mASTPrint = false;
+    mEmit3264 = true;
   }
 };
 
diff --git a/slang.cpp b/slang.cpp
index ec068d3..72bee50 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -226,9 +226,9 @@
 }
 
 clang::ASTConsumer *
-Slang::createBackend(const clang::CodeGenOptions &CodeGenOpts,
+Slang::createBackend(const RSCCOptions &Opts, const clang::CodeGenOptions &CodeGenOpts,
                      llvm::raw_ostream *OS, OutputType OT) {
-  return new Backend(mRSContext, &getDiagnostics(), CodeGenOpts,
+  return new Backend(mRSContext, &getDiagnostics(), Opts, CodeGenOpts,
                      getTargetOptions(), &mPragmas, OS, OT, getSourceManager(),
                      mAllowRSPrefix, mIsFilterscript);
 }
@@ -386,7 +386,7 @@
   return mDiagEngine->hasErrorOccurred() ? 1 : 0;
 }
 
-int Slang::compile() {
+int Slang::compile(const RSCCOptions &Opts) {
   if (mDiagEngine->hasErrorOccurred())
     return 1;
   if (mOS.get() == nullptr)
@@ -396,7 +396,7 @@
   createPreprocessor();
   createASTContext();
 
-  mBackend.reset(createBackend(CodeGenOpts, &mOS->os(), mOT));
+  mBackend.reset(createBackend(Opts, CodeGenOpts, &mOS->os(), mOT));
 
   // Inform the diagnostic client we are processing a source file
   mDiagClient->BeginSourceFile(LangOpts, mPP.get());
@@ -670,7 +670,7 @@
 
     mIsFilterscript = isFilterscript(InputFile);
 
-    if (Slang::compile() > 0)
+    if (Slang::compile(Opts) > 0)
       return false;
 
     if (!Opts.mJavaReflectionPackageName.empty()) {
diff --git a/slang.h b/slang.h
index 0848451..d5b8ddb 100644
--- a/slang.h
+++ b/slang.h
@@ -189,7 +189,8 @@
   void initPreprocessor();
   void initASTContext();
 
-  clang::ASTConsumer *createBackend(const clang::CodeGenOptions &CodeGenOpts,
+  clang::ASTConsumer *createBackend(const RSCCOptions &Opts,
+                                    const clang::CodeGenOptions &CodeGenOpts,
                                     llvm::raw_ostream *OS,
                                     OutputType OT);
 
@@ -239,7 +240,7 @@
 
   int generateDepFile();
 
-  int compile();
+  int compile(const RSCCOptions &Opts);
 
   char const *getErrorMessage() { return mDiagClient->str().c_str(); }
 
diff --git a/slang_backend.cpp b/slang_backend.cpp
index ff41367..631b654 100644
--- a/slang_backend.cpp
+++ b/slang_backend.cpp
@@ -71,6 +71,8 @@
 #include "slang_rs_export_var.h"
 #include "slang_rs_metadata.h"
 
+#include "rs_cc_options.h"
+
 #include "strip_unknown_attributes.h"
 #include "BitWriter_2_9/ReaderWriter_2_9.h"
 #include "BitWriter_2_9_func/ReaderWriter_2_9_func.h"
@@ -208,7 +210,7 @@
 }
 
 Backend::Backend(RSContext *Context, clang::DiagnosticsEngine *DiagEngine,
-                 const clang::CodeGenOptions &CodeGenOpts,
+                 const RSCCOptions &Opts, const clang::CodeGenOptions &CodeGenOpts,
                  const clang::TargetOptions &TargetOpts, PragmaList *Pragmas,
                  llvm::raw_ostream *OS, Slang::OutputType OT,
                  clang::SourceManager &SourceMgr, bool AllowRSPrefix,
@@ -217,7 +219,7 @@
       mOT(OT), mGen(nullptr), mPerFunctionPasses(nullptr),
       mPerModulePasses(nullptr), mCodeGenPasses(nullptr),
       mBufferOutStream(*mpOS), mContext(Context),
-      mSourceMgr(SourceMgr), mAllowRSPrefix(AllowRSPrefix),
+      mSourceMgr(SourceMgr), mASTPrint(Opts.mASTPrint), mAllowRSPrefix(AllowRSPrefix),
       mIsFilterscript(IsFilterscript), mExportVarMetadata(nullptr),
       mExportFuncMetadata(nullptr), mExportForEachNameMetadata(nullptr),
       mExportForEachSignatureMetadata(nullptr), mExportTypeMetadata(nullptr),
@@ -253,6 +255,9 @@
 void Backend::HandleTranslationUnit(clang::ASTContext &Ctx) {
   HandleTranslationUnitPre(Ctx);
 
+  if (mASTPrint)
+    Ctx.getTranslationUnitDecl()->dump();
+
   mGen->HandleTranslationUnit(Ctx);
 
   // Here, we complete a translation unit (whole translation unit is now in LLVM
diff --git a/slang_backend.h b/slang_backend.h
index e3dbdef..ad88d97 100644
--- a/slang_backend.h
+++ b/slang_backend.h
@@ -87,6 +87,8 @@
 
   clang::SourceManager &mSourceMgr;
 
+  bool mASTPrint;
+
   bool mAllowRSPrefix;
 
   bool mIsFilterscript;
@@ -136,6 +138,7 @@
  public:
   Backend(RSContext *Context,
             clang::DiagnosticsEngine *DiagEngine,
+            const RSCCOptions &Opts,
             const clang::CodeGenOptions &CodeGenOpts,
             const clang::TargetOptions &TargetOpts,
             PragmaList *Pragmas,