Make bitcode wrapper info available to MetadataExtractor.

Copy bitcode wrapper information (compiler version, optimization
level) from bitcode wrapper to Module metadata, where it can be found
by MetadataExtractor instantiated from Module.  Previously, such a
MetadataExtractor ignored the information in the bitcode wrapper;
instead, it
- nonsensically set compiler version to RS_VERSION, which is an API
  level rather than a slang version; and
- set optimization level to 3.

Remove unused MetadataExtractor::getTargetAPI():
- Old behavior:
  - For user bitcode, got actual targetAPI.
  - For libclcore, got 0.
  - For linked bitcode (user bitcode + libclcore), got
    uninitialized/garbage value.
- It's not clear what a sensible value would be for libclcore or for
  linked bitcode (or perhaps it should be an error to query the
  targetAPI in those cases).  What a sensible value would be depends
  on how we intend to use it.

This change enables a forthcoming libbcc change that needs to know the
slang version.

Bug: http://b/29154200
Bug: http://b/28070272

Test: full_fugu-eng
      Tried (  modified slang, modified bcc) and
            (unmodified slang, modified bcc):
      - libbcc/tests/run_lit_tests.sh; RsTest; cts -m RenderscriptTest
      - confirmed that our driver is loaded rather than libPVRRS.so
      - By instrumenting modified bcc and running RsTest, confirmed
that:
        - MetadataExtractor properly obtains slang version from Module.
      "Modified slang" is a forthcoming slang change that changes
        the slang version.

Change-Id: Ifc9c1348c96a88bf7ddb344721f67f89359a4fe6
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index 431e586..78d94e5 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -22,6 +22,8 @@
 #define LOG_TAG "bcinfo"
 #include <log/log.h>
 
+#include "Assert.h"
+
 #include "llvm/Bitcode/ReaderWriter.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/LLVMContext.h"
@@ -173,6 +175,8 @@
 // unit.
 static const llvm::StringRef DebugInfoMetadataName = "llvm.dbg.cu";
 
+const char MetadataExtractor::kWrapperMetadataName[] = "#rs_wrapper";
+
 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
     : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
       mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
@@ -186,7 +190,6 @@
       mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
       mBuildChecksum(nullptr), mHasDebugInfo(false) {
   BitcodeWrapper wrapper(bitcode, bitcodeSize);
-  mTargetAPI = wrapper.getTargetAPI();
   mCompilerVersion = wrapper.getCompilerVersion();
   mOptimizationLevel = wrapper.getOptimizationLevel();
 }
@@ -203,8 +206,14 @@
       mObjectSlotCount(0), mObjectSlotList(nullptr),
       mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
       mBuildChecksum(nullptr) {
-  mCompilerVersion = RS_VERSION;  // Default to the actual current version.
-  mOptimizationLevel = 3;
+  const llvm::NamedMDNode *const wrapperMDNode = module->getNamedMetadata(kWrapperMetadataName);
+  bccAssert((wrapperMDNode != nullptr) && (wrapperMDNode->getNumOperands() == 1));
+  const llvm::MDNode *const wrapperMDTuple = wrapperMDNode->getOperand(0);
+
+  bool success = true;
+  success &= extractUIntFromMetadataString(&mCompilerVersion, wrapperMDTuple->getOperand(0));
+  success &= extractUIntFromMetadataString(&mOptimizationLevel, wrapperMDTuple->getOperand(1));
+  bccAssert(success);
 }
 
 
diff --git a/bcinfo/include/bcinfo/MetadataExtractor.h b/bcinfo/include/bcinfo/MetadataExtractor.h
index d1de4fe..85dcd5d 100644
--- a/bcinfo/include/bcinfo/MetadataExtractor.h
+++ b/bcinfo/include/bcinfo/MetadataExtractor.h
@@ -105,7 +105,6 @@
   size_t mObjectSlotCount;
   const uint32_t *mObjectSlotList;
 
-  uint32_t mTargetAPI;
   uint32_t mCompilerVersion;
   uint32_t mOptimizationLevel;
 
@@ -131,6 +130,12 @@
                               uint32_t Signature);
 
  public:
+
+  // Name of metadata node where information extracted from the
+  // bitcode wrapper should have been stored when we use the
+  // MetadataExtractor constructor that takes a Module as a parameter.
+  static const char kWrapperMetadataName[];
+
   /**
    * Reads metadata from \p bitcode.
    *
@@ -143,6 +148,8 @@
    * Reads metadata from \p module.
    *
    * \param module - input module.
+   *
+   * module must contain a metadata node named kWrapperMetadataName.
    */
   explicit MetadataExtractor(const llvm::Module *module);
 
@@ -156,16 +163,6 @@
   bool extract();
 
   /**
-   * \return target API level of this bitcode.
-   *
-   * The target API is used during the SDK compilation to provide proper
-   * visibility of the RenderScript runtime API functions.
-   */
-  uint32_t getTargetAPI() const {
-    return mTargetAPI;
-  }
-
-  /**
    * \return number of exported global variables (slots) in this script/module.
    */
   size_t getExportVarCount() const {
@@ -272,14 +269,17 @@
   }
 
   /**
-   * \return compiler version that generated this bitcode.
+   * \return compiler version indicating which guarantees this bitcode is
+   *         known to obey.
    */
   uint32_t getCompilerVersion() const {
     return mCompilerVersion;
   }
 
   /**
-   * \return compiler optimization level for this bitcode.
+   * \return compiler optimization level for this bitcode.  In the case of
+   *         linked bitcode (user_bitcode + libclcore_bitcode), this is the
+   *         optimization level of user_bitcode.
    */
   uint32_t getOptimizationLevel() const {
     return mOptimizationLevel;
diff --git a/include/bcc/Script.h b/include/bcc/Script.h
index ad18ac6..b4135c5 100644
--- a/include/bcc/Script.h
+++ b/include/bcc/Script.h
@@ -18,6 +18,7 @@
 #define BCC_SCRIPT_H
 
 #include <llvm/Support/CodeGen.h>
+#include "bcc/Source.h"
 
 namespace llvm {
 class Module;
@@ -39,9 +40,6 @@
   // TODO(jeanluc) Verify that the lifetime is managed correctly.
   Source *mSource;
 
-  // Currently unused.  Will be used in an upcoming CL to fix small_struct bug.
-  unsigned mCompilerVersion;
-
   llvm::CodeGenOpt::Level mOptimizationLevel;
 
   RSLinkRuntimeCallback mLinkRuntimeCallback;
@@ -63,12 +61,10 @@
 
   bool LinkRuntime(const char *rt_path);
 
-  void setCompilerVersion(unsigned pCompilerVersion) {
-    mCompilerVersion = pCompilerVersion;
+  unsigned getCompilerVersion() const {
+    return getSource().getCompilerVersion();
   }
 
-  unsigned getCompilerVersion() const { return mCompilerVersion; }
-
   void setOptimizationLevel(llvm::CodeGenOpt::Level pOptimizationLevel) {
     mOptimizationLevel = pOptimizationLevel;
   }
diff --git a/include/bcc/Source.h b/include/bcc/Source.h
index ad337c9..2c85791 100644
--- a/include/bcc/Source.h
+++ b/include/bcc/Source.h
@@ -64,16 +64,21 @@
   static Source *CreateFromModule(BCCContext &pContext,
                                   const char* name,
                                   llvm::Module &pModule,
+                                  uint32_t compilerVersion,
+                                  uint32_t optimizationLevel,
                                   bool pNoDelete = false);
 
-  static Source *CreateEmpty(BCCContext &pContext, const std::string &pName);
-
   const std::string& getName() const { return mName; }
 
   // Merge the current source with pSource. pSource
   // will be destroyed after successfully merged. Return false on error.
   bool merge(Source &pSource);
 
+  unsigned getCompilerVersion() const;
+
+  void getWrapperInformation(unsigned *compilerVersion,
+                             unsigned *optimizationLevel) const;
+
   inline BCCContext &getContext()
   { return mContext; }
   inline const BCCContext &getContext() const
diff --git a/lib/Assert.h b/lib/Assert.h
index 2ce3a83..44c3804 100644
--- a/lib/Assert.h
+++ b/lib/Assert.h
@@ -31,8 +31,10 @@
 
 #else
 
-#define LOG_TAG "bcc"
-#include <log/log.h>
+#ifndef LOG_TAG
+#   define LOG_TAG "bcc"
+#   include <log/log.h>
+#endif
 
 #define __ABORT_ON_FAILURES 1
 
diff --git a/lib/RSCompilerDriver.cpp b/lib/RSCompilerDriver.cpp
index 599afd6..6ed7400 100644
--- a/lib/RSCompilerDriver.cpp
+++ b/lib/RSCompilerDriver.cpp
@@ -267,9 +267,8 @@
   script.setEmbedGlobalInfo(mEmbedGlobalInfo);
   script.setEmbedGlobalInfoSkipConstant(mEmbedGlobalInfoSkipConstant);
 
-  // Read information from bitcode wrapper.
+  // Read optimization level from bitcode wrapper.
   bcinfo::BitcodeWrapper wrapper(pBitcode, pBitcodeSize);
-  script.setCompilerVersion(wrapper.getCompilerVersion());
   script.setOptimizationLevel(static_cast<llvm::CodeGenOpt::Level>(
                               wrapper.getOptimizationLevel()));
 
@@ -324,8 +323,22 @@
   llvm::LLVMContext& context = Context.getLLVMContext();
   llvm::Module module("Merged Script Group", context);
 
+  unsigned wrapperCompilerVersion = 0, wrapperOptimizationLevel = 0;
+  bool gotFirstSource = false;
   llvm::Linker linker(module);
   for (Source* source : sources) {
+    unsigned sourceWrapperCompilerVersion, sourceWrapperOptimizationLevel;
+    source->getWrapperInformation(&sourceWrapperCompilerVersion, &sourceWrapperOptimizationLevel);
+    if (gotFirstSource) {
+      if ((wrapperCompilerVersion != sourceWrapperCompilerVersion) ||
+          (wrapperOptimizationLevel != sourceWrapperOptimizationLevel))
+        ALOGE("ScriptGroup source files have inconsistent metadata");
+        return false;
+    } else {
+      wrapperCompilerVersion = sourceWrapperCompilerVersion;
+      wrapperOptimizationLevel = sourceWrapperOptimizationLevel;
+      gotFirstSource = true;
+    }
     std::unique_ptr<llvm::Module> sourceModule(&source->getModule());
     if (linker.linkInModule(std::move(sourceModule))) {
       ALOGE("Linking for module in source failed.");
@@ -333,6 +346,13 @@
     }
     // source->getModule() is destroyed after linking.
     source->markModuleDestroyed();
+    // linking copies metadata from source->getModule(), but we don't
+    // want the wrapper metadata (we'll be reconstructing this when we
+    // instantiate a Source instance from the new Module).
+    llvm::NamedMDNode *const wrapperMDNode =
+        module.getNamedMetadata(bcinfo::MetadataExtractor::kWrapperMetadataName);
+    bccAssert(wrapperMDNode != nullptr);
+    module.eraseNamedMetadata(wrapperMDNode);
   }
 
   // ---------------------------------------------------------------------------
@@ -376,7 +396,9 @@
   // ---------------------------------------------------------------------------
 
   const std::unique_ptr<Source> source(
-      Source::CreateFromModule(Context, pOutputFilepath, module, true));
+      Source::CreateFromModule(Context, pOutputFilepath, module,
+                               wrapperCompilerVersion, wrapperOptimizationLevel,
+                               true));
   Script script(source.get());
 
   // Embed the info string directly in the ELF
diff --git a/lib/Script.cpp b/lib/Script.cpp
index 6381b34..950d82a 100644
--- a/lib/Script.cpp
+++ b/lib/Script.cpp
@@ -22,11 +22,14 @@
 #include "bcc/CompilerConfig.h"
 #include "bcc/Source.h"
 
+#include "bcinfo/MetadataExtractor.h"
+
+#include <llvm/IR/Module.h>
+
 using namespace bcc;
 
 Script::Script(Source *pSource)
     : mSource(pSource),
-      mCompilerVersion(0),
       mOptimizationLevel(llvm::CodeGenOpt::Aggressive),
       mLinkRuntimeCallback(nullptr), mEmbedInfo(false), mEmbedGlobalInfo(false),
       mEmbedGlobalInfoSkipConstant(false) {}
@@ -48,6 +51,31 @@
                          &libclcore_source->getModule());
   }
 
+  // For every named metadata node in the source (libclcore_source),
+  // the merge process ensures there is a same-named metadata node in
+  // the destination (mSource) (creating it if necessary) and appends
+  // all of the source node's operands to the end of the destination
+  // node's operands.  In the case of the wrapper metadata
+  //
+  //   kWrapperMetadataName -> (compilerVersion, optimizationLevel)
+  //
+  // this is not the behavior we want.  Instead, we want to retain the
+  // source wrapper metadata:
+  // - compiler version in libclcore_source is 0, a nonsensical value.
+  //   As documented in slang_version.h, libclcore_source must not
+  //   violate any compiler version guarantees, so the right thing to
+  //   do is retain the compiler version from source, which specifies
+  //   which guarantees source (and hence the merged code) satisfies.
+  // - optimization level in source and libclcore_source is meaningful.
+  //   We simply define the optimization level in the linked code to
+  //   be the optimization level of source.
+  // The easiest way to retain the source wrapper metadata is to delete
+  // the libclcore_source wrapper metadata.
+  llvm::Module &libclcore_module = libclcore_source->getModule();
+  llvm::NamedMDNode *const wrapperMDNode =
+      libclcore_module.getNamedMetadata(bcinfo::MetadataExtractor::kWrapperMetadataName);
+  bccAssert(wrapperMDNode != nullptr);
+  libclcore_module.eraseNamedMetadata(wrapperMDNode);
   if (!mSource->merge(*libclcore_source)) {
     ALOGE("Failed to link Renderscript library '%s'!", core_lib);
     delete libclcore_source;
diff --git a/lib/Source.cpp b/lib/Source.cpp
index 3ec08e4..d99eb10 100644
--- a/lib/Source.cpp
+++ b/lib/Source.cpp
@@ -22,6 +22,7 @@
 #include <new>
 
 #include <llvm/ADT/STLExtras.h>
+#include <llvm/ADT/StringExtras.h>
 #include <llvm/Bitcode/ReaderWriter.h>
 #include <llvm/IR/LLVMContext.h>
 #include <llvm/IR/Module.h>
@@ -30,6 +31,8 @@
 #include <llvm/Support/MemoryBuffer.h>
 #include "llvm/Support/raw_ostream.h"
 
+#include "Assert.h"
+#include "bcinfo/BitcodeWrapper.h"
 #include "bcinfo/MetadataExtractor.h"
 
 #include "BCCContextImpl.h"
@@ -52,10 +55,45 @@
   return std::move(moduleOrError.get());
 }
 
+static void helper_get_module_metadata_from_bitcode_wrapper(
+    uint32_t *compilerVersion, uint32_t *optimizationLevel,
+    const bcinfo::BitcodeWrapper &wrapper) {
+  *compilerVersion = wrapper.getCompilerVersion();
+  *optimizationLevel = wrapper.getOptimizationLevel();
+}
+
+static void helper_set_module_metadata_from_bitcode_wrapper(llvm::Module &module,
+                                                            const uint32_t compilerVersion,
+                                                            const uint32_t optimizationLevel) {
+  llvm::LLVMContext &llvmContext = module.getContext();
+
+  llvm::NamedMDNode *const wrapperMDNode =
+      module.getOrInsertNamedMetadata(bcinfo::MetadataExtractor::kWrapperMetadataName);
+  bccAssert(wrapperMDNode->getNumOperands() == 0);  // expect to have just now created this node
+
+  llvm::SmallVector<llvm::Metadata *, 2> wrapperInfo = {
+    llvm::MDString::get(llvmContext, llvm::utostr(compilerVersion)),
+    llvm::MDString::get(llvmContext, llvm::utostr(optimizationLevel))
+  };
+
+  wrapperMDNode->addOperand(llvm::MDTuple::get(llvmContext, wrapperInfo));
+}
+
 } // end anonymous namespace
 
 namespace bcc {
 
+unsigned Source::getCompilerVersion() const {
+  return bcinfo::MetadataExtractor(&getModule()).getCompilerVersion();
+}
+
+void Source::getWrapperInformation(unsigned *compilerVersion,
+                                   unsigned *optimizationLevel) const {
+  const bcinfo::MetadataExtractor &me = bcinfo::MetadataExtractor(&getModule());
+  *compilerVersion = me.getCompilerVersion();
+  *optimizationLevel = me.getOptimizationLevel();
+}
+
 void Source::setModule(llvm::Module *pModule) {
   if (!mNoDelete && (mModule != pModule)) delete mModule;
   mModule = pModule;
@@ -84,7 +122,12 @@
     return nullptr;
   }
 
-  Source *result = CreateFromModule(pContext, pName, *module, /* pNoDelete */false);
+  uint32_t compilerVersion, optimizationLevel;
+  helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel,
+                                                  bcinfo::BitcodeWrapper(pBitcode, pBitcodeSize));
+  Source *result = CreateFromModule(pContext, pName, *module,
+                                    compilerVersion, optimizationLevel,
+                                    /* pNoDelete */false);
   if (result == nullptr) {
     delete module;
   }
@@ -103,6 +146,11 @@
   }
   std::unique_ptr<llvm::MemoryBuffer> input_data = std::move(mb_or_error.get());
 
+  uint32_t compilerVersion, optimizationLevel;
+  helper_get_module_metadata_from_bitcode_wrapper(&compilerVersion, &optimizationLevel,
+                                                  bcinfo::BitcodeWrapper(input_data->getBufferStart(),
+                                                                         input_data->getBufferSize()));
+
   std::unique_ptr<llvm::MemoryBuffer> input_memory(input_data.release());
   auto managedModule = helper_load_bitcode(pContext.mImpl->mLLVMContext,
                                            std::move(input_memory));
@@ -114,7 +162,9 @@
     return nullptr;
   }
 
-  Source *result = CreateFromModule(pContext, pPath.c_str(), *module, /* pNoDelete */false);
+  Source *result = CreateFromModule(pContext, pPath.c_str(), *module,
+                                    compilerVersion, optimizationLevel,
+                                    /* pNoDelete */false);
   if (result == nullptr) {
     delete module;
   }
@@ -123,6 +173,8 @@
 }
 
 Source *Source::CreateFromModule(BCCContext &pContext, const char* name, llvm::Module &pModule,
+                                 const uint32_t compilerVersion,
+                                 const uint32_t optimizationLevel,
                                  bool pNoDelete) {
   std::string ErrorInfo;
   llvm::raw_string_ostream ErrorStream(ErrorInfo);
@@ -138,6 +190,7 @@
     ALOGE("Out of memory during Source object allocation for `%s'!",
           pModule.getModuleIdentifier().c_str());
   }
+  helper_set_module_metadata_from_bitcode_wrapper(pModule, compilerVersion, optimizationLevel);
   return result;
 }
 
@@ -168,24 +221,6 @@
   return true;
 }
 
-Source *Source::CreateEmpty(BCCContext &pContext, const std::string &pName) {
-  // Create an empty module
-  llvm::Module *module =
-      new (std::nothrow) llvm::Module(pName, pContext.mImpl->mLLVMContext);
-
-  if (module == nullptr) {
-    ALOGE("Out of memory when creating empty LLVM module `%s'!", pName.c_str());
-    return nullptr;
-  }
-
-  Source *result = CreateFromModule(pContext, pName.c_str(), *module, /* pNoDelete */false);
-  if (result == nullptr) {
-    delete module;
-  }
-
-  return result;
-}
-
 const std::string &Source::getIdentifier() const {
   return mModule->getModuleIdentifier();
 }
diff --git a/tests/libbcc/getelementptr.ll b/tests/libbcc/getelementptr.ll
index 1cf201a..ee46bc8 100644
--- a/tests/libbcc/getelementptr.ll
+++ b/tests/libbcc/getelementptr.ll
@@ -61,6 +61,12 @@
 !\23rs_export_foreach_name = !{!3, !4}
 !\23rs_export_foreach = !{!5, !6}
 
+; The following named metadata would not be present in a bitcode file,
+; but instead synthesized by bcc from the bitcode wrapper.  However,
+; for this test case, we're not running bcc, but instead opt, and so
+; we never get the opportunity to synthesize this named metadata.
+!\23rs_wrapper = !{!7}
+
 !0 = !{!"clang version 3.6 "}
 !1 = !{!"version", !"1"}
 !2 = !{!"java_package_name", !"foo"}
@@ -68,3 +74,4 @@
 !4 = !{!"foo"}
 !5 = !{!"91"}
 !6 = !{!"123"}
+!7 = !{!"0", !"3"}
diff --git a/tests/libbcc/tbaa-through-alloca.ll b/tests/libbcc/tbaa-through-alloca.ll
index 5b0a270..cf44545 100644
--- a/tests/libbcc/tbaa-through-alloca.ll
+++ b/tests/libbcc/tbaa-through-alloca.ll
@@ -54,6 +54,12 @@
 !\23rs_export_type = !{!7}
 !\25int5 = !{!8}
 
+; The following named metadata would not be present in a bitcode file,
+; but instead synthesized by bcc from the bitcode wrapper.  However,
+; for this test case, we're not running bcc, but instead opt, and so
+; we never get the opportunity to synthesize this named metadata.
+!\23rs_wrapper = !{!15}
+
 !0 = !{!"clang version 3.6 "}
 !1 = !{!"version", !"1"}
 !2 = !{!"java_package_name", !"foo"}
@@ -69,3 +75,4 @@
 !12 = !{!"Simple C/C++ TBAA"}
 !13 = !{i64 0, i64 20, !14}
 !14 = !{!11, !11, i64 0}
+!15 = !{!"0", !"3"}
diff --git a/tests/libbcc/tbaa.ll b/tests/libbcc/tbaa.ll
index 6d8cb48..c186f3e 100644
--- a/tests/libbcc/tbaa.ll
+++ b/tests/libbcc/tbaa.ll
@@ -34,6 +34,12 @@
 !\23rs_export_foreach_name = !{!3, !4}
 !\23rs_export_foreach = !{!5, !6}
 
+; The following named metadata would not be present in a bitcode file,
+; but instead synthesized by bcc from the bitcode wrapper.  However,
+; for this test case, we're not running bcc, but instead opt, and so
+; we never get the opportunity to synthesize this named metadata.
+!\23rs_wrapper = !{!7}
+
 !0 = !{!"clang version 3.6 "}
 !1 = !{!"version", !"1"}
 !2 = !{!"java_package_name", !"foo"}
@@ -41,3 +47,4 @@
 !4 = !{!"add1"}
 !5 = !{!"0"}
 !6 = !{!"35"}
+!7 = !{!"0", !"3"}