Merge "Enhance diagnostic options."
diff --git a/Android.mk b/Android.mk
index 091a852..b3f3bc4 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 2015c10..2339cd7 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">;
@@ -124,6 +124,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 2876726..ef8c2d2 100644
--- a/rs_cc_options.cpp
+++ b/rs_cc_options.cpp
@@ -228,11 +228,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 =
@@ -243,6 +254,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.
 
@@ -259,11 +289,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 9984260..d27732e 100644
--- a/rs_cc_options.h
+++ b/rs_cc_options.h
@@ -102,6 +102,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;
 
@@ -117,7 +120,8 @@
     mDebugEmission = 0;
     mOptimizationLevel = llvm::CodeGenOpt::Aggressive;
     mVerbose = false;
-    mEmit3264 = false;
+    mASTPrint = false;
+    mEmit3264 = true;
   }
 };
 
diff --git a/slang.cpp b/slang.cpp
index 4b3547d..02a77bb 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);
 }
@@ -388,7 +388,7 @@
   return mDiagEngine->hasErrorOccurred() ? 1 : 0;
 }
 
-int Slang::compile() {
+int Slang::compile(const RSCCOptions &Opts) {
   if (mDiagEngine->hasErrorOccurred())
     return 1;
   if (mOS.get() == nullptr)
@@ -398,7 +398,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());
@@ -674,7 +674,7 @@
 
     CodeGenOpts.MainFileName = mInputFileName;
 
-    if (Slang::compile() > 0)
+    if (Slang::compile(Opts) > 0)
       return false;
 
     if (!Opts.mJavaReflectionPackageName.empty()) {
diff --git a/slang.h b/slang.h
index e83d520..ac128a9 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(bool PhonyTarget);
 
-  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 4899790..0936494 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"
 
 namespace slang {
@@ -205,7 +207,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,
@@ -214,7 +216,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), mExportReduceMetadata(nullptr),
@@ -235,6 +237,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 f655ad8..83912fd 100644
--- a/slang_backend.h
+++ b/slang_backend.h
@@ -85,6 +85,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,