Introduce RSInfo and its reader/extractor/writer.

This commit only adds files that implements RSInfo class and DOES
NOT switch to use it.

RSInfo defines the new file format to cache the metadata and
RS-specific information from the source bitcode.

It's the replacement of the old "MC cache" whose name is ambiguous
and some fields within that are deprecated after legacy JIT was
removed.

Reader of RSInfo reads information from the file we called "RS info
file." It will replace MCCacheReader.

Extractor of RSInfo extracts information from the metadata section of
the source bitcode. It will replace MetadataExtractor.

Writer of RSInfo serializes a RSInfo object to a file such that
we can load it quickly using RSInfo reader later. It will replace
MCCacheWriter.

RSInfo unifies the interfaces to get the RS-specific information
such as #rs_export_var supplied by the developers either from file
(RS info file) or from the source bitcode. Later commit will prove
that.

RSInfo uses signature ("\0rsinfo\n") which is different from the
old MC cache ("\0bcc").

The version (MCO_VERSION in bcc_mccache.h) is increased by 1 in this
commit since we remove res_type in MCO_Dependency. RSInfo inherits
the version number comes from old MC cache therefore its version
number starts with 3.
diff --git a/lib/ExecutionEngine/RSInfoWriter.cpp b/lib/ExecutionEngine/RSInfoWriter.cpp
new file mode 100644
index 0000000..d54fb41
--- /dev/null
+++ b/lib/ExecutionEngine/RSInfoWriter.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+//===----------------------------------------------------------------------===//
+// This file implements RSInfo::write()
+//===----------------------------------------------------------------------===//
+
+#include "RSInfo.h"
+
+#include "DebugHelper.h"
+#include "OutputFile.h"
+
+using namespace bcc;
+
+namespace {
+
+template<typename ItemType, typename ItemContainer> inline bool
+helper_adapt_list_item(ItemType &pResult, const RSInfo &pInfo,
+                       const typename ItemContainer::const_iterator &pItem);
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::DependencyTableItem, RSInfo::DependencyTableTy>(
+    rsinfo::DependencyTableItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::DependencyTableTy::const_iterator &pItem) {
+  pResult.id = pInfo.getStringIdxInPool(pItem->first);
+  pResult.sha1 =
+      pInfo.getStringIdxInPool(reinterpret_cast<const char *>(pItem->second));
+
+  if (pResult.id == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS dependency table contains invalid source id string '%s'.",
+          pItem->first);
+    return false;
+  }
+
+  if (pResult.sha1 == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS dependency table contains invalid SHA-1 checksum string in '%s'.",
+          pItem->first);
+    return false;
+  }
+
+  return true;
+}
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
+    rsinfo::PragmaItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::PragmaListTy::const_iterator &pItem) {
+  pResult.key = pInfo.getStringIdxInPool(pItem->first);
+  pResult.value = pInfo.getStringIdxInPool(pItem->second);
+
+  if (pResult.key == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS pragma list contains invalid string '%s' for key.", pItem->first);
+    return false;
+  }
+
+  if (pResult.value == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS pragma list contains invalid string '%s' for value.",
+          pItem->second);
+    return false;
+  }
+
+  return true;
+}
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
+    rsinfo::ObjectSlotItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::ObjectSlotListTy::const_iterator &pItem) {
+  pResult.slot = *pItem;
+  return true;
+}
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
+    rsinfo::ExportVarNameItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::ExportVarNameListTy::const_iterator &pItem) {
+  pResult.name = pInfo.getStringIdxInPool(*pItem);
+
+  if (pResult.name == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS export vars contains invalid string '%s' for name.", *pItem);
+    return false;
+  }
+
+  return true;
+}
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::ExportFuncNameItem,
+                       RSInfo::ExportFuncNameListTy>(
+    rsinfo::ExportFuncNameItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::ExportFuncNameListTy::const_iterator &pItem) {
+  pResult.name = pInfo.getStringIdxInPool(*pItem);
+
+  if (pResult.name == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS export funcs contains invalid string '%s' for name.", *pItem);
+    return false;
+  }
+
+  return true;
+}
+
+template<> inline bool
+helper_adapt_list_item<rsinfo::ExportForeachFuncItem,
+                       RSInfo::ExportForeachFuncListTy>(
+    rsinfo::ExportForeachFuncItem &pResult,
+    const RSInfo &pInfo,
+    const RSInfo::ExportForeachFuncListTy::const_iterator &pItem) {
+  pResult.name = pInfo.getStringIdxInPool(pItem->first);
+  pResult.signature = pItem->second;
+
+  if (pResult.name == rsinfo::gInvalidStringIndex) {
+    ALOGE("RS export foreach contains invalid string '%s' for name.",
+          pItem->first);
+    return false;
+  }
+
+  return true;
+}
+
+template<typename ItemType, typename ItemContainer>
+inline bool helper_write_list(OutputFile &pOutput,
+                              const RSInfo &pInfo,
+                              const rsinfo::ListHeader &pHeader,
+                              ItemContainer &pList) {
+  ItemType item;
+
+  for (typename ItemContainer::const_iterator item_iter = pList.begin(),
+          item_end = pList.end(); item_iter != item_end; item_iter++) {
+    // Convert each entry in the pList to ItemType.
+    if (!helper_adapt_list_item<ItemType, ItemContainer>(item,
+                                                         pInfo,
+                                                         item_iter)) {
+      return false;
+    }
+    // And write out an item.
+    if (pOutput.write(&item, sizeof(item)) != sizeof(item)) {
+      ALOGE("Cannot write out item of %s for RSInfo file %s! (%s)",
+            rsinfo::GetItemTypeName<ItemType>(), pOutput.getName().c_str(),
+            pOutput.getErrorMessage().c_str());
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // end anonymous namespace
+
+bool RSInfo::write(OutputFile &pOutput) {
+  off_t initial_offset = pOutput.tell();
+  const char *output_filename = pOutput.getName().c_str();
+
+  if (pOutput.hasError()) {
+    ALOGE("Invalid RS info file %s for output! (%s)",
+          output_filename, pOutput.getErrorMessage().c_str());
+    return false;
+  }
+
+  // Layout.
+  if (!layout(initial_offset)) {
+    return false;
+  }
+
+  // Write header.
+  if (pOutput.write(&mHeader, sizeof(mHeader)) != sizeof(mHeader)) {
+    ALOGE("Cannot write out the header for RSInfo file %s! (%s)",
+          output_filename, pOutput.getErrorMessage().c_str());
+    return false;
+  }
+
+  // Write string pool.
+  if (static_cast<size_t>(pOutput.write(mStringPool, mHeader.strPoolSize))
+          != mHeader.strPoolSize) {
+    ALOGE("Cannot write out the string pool for RSInfo file %s! (%s)",
+          output_filename, pOutput.getErrorMessage().c_str());
+    return false;
+  }
+
+  // Write dependencyTable.
+  if (!helper_write_list<rsinfo::DependencyTableItem, DependencyTableTy>
+        (pOutput, *this, mHeader.dependencyTable, mDependencyTable)) {
+    return false;
+  }
+
+  // Write pragmaList.
+  if (!helper_write_list<rsinfo::PragmaItem, PragmaListTy>
+        (pOutput, *this, mHeader.pragmaList, mPragmas)) {
+    return false;
+  }
+
+  // Write objectSlotList.
+  if (!helper_write_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
+        (pOutput, *this, mHeader.objectSlotList, mObjectSlots)) {
+    return false;
+  }
+
+  // Write exportVarNameList.
+  if (!helper_write_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
+        (pOutput, *this, mHeader.exportVarNameList, mExportVarNames)) {
+    return false;
+  }
+
+  // Write exportFuncNameList.
+  if (!helper_write_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
+        (pOutput, *this, mHeader.exportFuncNameList, mExportFuncNames)) {
+    return false;
+  }
+
+  // Write exportForeachFuncList.
+  if (!helper_write_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
+        (pOutput, *this, mHeader.exportForeachFuncList, mExportForeachFuncs)) {
+    return false;
+  }
+
+  return true;
+}