RSInfoExtractor.cpp revision 6f3138bbc93b7105ddb49a803c15c3f98077f533
11e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang/*
21e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * Copyright 2012, The Android Open Source Project
31e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang *
41e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
51e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * you may not use this file except in compliance with the License.
61e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * You may obtain a copy of the License at
71e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang *
81e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
91e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang *
101e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * Unless required by applicable law or agreed to in writing, software
111e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
121e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * See the License for the specific language governing permissions and
141e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * limitations under the License.
151e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang */
161e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
171e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang//===----------------------------------------------------------------------===//
181e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// This file implements RSInfo::ExtractFromSource()
191e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang//===----------------------------------------------------------------------===//
20e198abec6c5e3eab380ccf6897b0a0b9c2dd92ddStephen Hines#include "bcc/Renderscript/RSInfo.h"
211e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
221e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang#include <llvm/Constants.h>
231e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang#include <llvm/Metadata.h>
241e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang#include <llvm/Module.h>
251e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
26c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Source.h"
27ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h"
281e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
291e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changusing namespace bcc;
301e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
311e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changnamespace {
321e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
331e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where pragma info resides (should be synced with
341e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// slang.cpp)
351e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef pragma_metadata_name("#pragma");
361e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
371e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang/*
381e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * The following names should be synced with the one appeared in
391e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * slang_rs_metadata.h.
401e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang */
411e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where exported variable names reside
421e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef export_var_metadata_name("#rs_export_var");
431e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
441e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where exported function names reside
451e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef export_func_metadata_name("#rs_export_func");
461e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
471e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where exported ForEach name information resides
481e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef export_foreach_name_metadata_name("#rs_export_foreach_name");
491e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
501e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where exported ForEach signature information resides
511e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef export_foreach_metadata_name("#rs_export_foreach");
521e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
531e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Name of metadata node where RS object slot info resides (should be
541e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst llvm::StringRef object_slot_metadata_name("#rs_object_slots");
551e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
561e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changinline llvm::StringRef getStringFromOperand(const llvm::Value *pString) {
571e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if ((pString != NULL) && (pString->getValueID() == llvm::Value::MDStringVal)) {
581e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    return static_cast<const llvm::MDString *>(pString)->getString();
591e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
601e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return llvm::StringRef();
611e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang}
621e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
631e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changtemplate<size_t NumOperands>
641e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changinline size_t getMetadataStringLength(const llvm::NamedMDNode *pMetadata) {
651e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (pMetadata == NULL) {
661e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    return 0;
671e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
681e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
691e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  size_t string_size = 0;
701e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  for (unsigned i = 0, e = pMetadata->getNumOperands(); i < e; i++) {
711e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    llvm::MDNode *node = pMetadata->getOperand(i);
721e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    if ((node != NULL) && (node->getNumOperands() >= NumOperands)) {
731e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      // Compiler try its best to unroll this loop since NumOperands is a
741e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      // template parameter (therefore the number of iteration can be determined
751e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      // at compile-time and it's usually small.)
761e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      for (unsigned j = 0; j < NumOperands; j++) {
771e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        llvm::StringRef s = getStringFromOperand(node->getOperand(j));
781e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        if (s.size() > 0) {
791e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          // +1 is for the null-terminator at the end of string.
801e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          string_size += (s.size() + 1);
811e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        }
821e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
831e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
841e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
851e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
861e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return string_size;
871e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang}
881e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
891e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Write a string pString to the string pool pStringPool at offset pWriteStart.
901e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang// Return the pointer the pString resides within the string pool.
911e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changconst char *writeString(const llvm::StringRef &pString, char *pStringPool,
921e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                        off_t *pWriteStart) {
931e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (pString.empty()) {
941e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    return pStringPool;
951e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
961e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
971e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  char *pStringWriteStart = pStringPool + *pWriteStart;
981e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Copy the string.
991e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  ::memcpy(pStringWriteStart, pString.data(), pString.size());
1001e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Write null-terminator at the end of the string.
1011e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  pStringWriteStart[ pString.size() ] = '\0';
1021e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Update pWriteStart.
1031e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  *pWriteStart += (pString.size() + 1);
1041e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1051e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return pStringWriteStart;
1061e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang}
1071e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1081e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changbool writeDependency(const std::string &pSourceName, const uint8_t *pSHA1,
1091e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                     char *pStringPool, off_t *pWriteStart,
1101e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                     RSInfo::DependencyTableTy &pDepTable) {
1111e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const char *source_name = writeString(pSourceName, pStringPool, pWriteStart);
1121e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1131e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  uint8_t *sha1 = reinterpret_cast<uint8_t *>(pStringPool + *pWriteStart);
1141e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
115f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  // SHA-1 is special. It's size of SHA1_DIGEST_LENGTH (=20) bytes long without
116f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  // null-terminator.
117f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  ::memcpy(sha1, pSHA1, SHA1_DIGEST_LENGTH);
1181e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Record in the result RSInfo object.
1191e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  pDepTable.push(std::make_pair(source_name, sha1));
1201e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Update the string pool pointer.
121f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  *pWriteStart += SHA1_DIGEST_LENGTH;
1221e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1231e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return true;
1241e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang}
1251e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1261e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang} // end anonymous namespace
1271e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1281e2adce6df4414d827149ec563c9c89f21ea7426Zonr ChangRSInfo *RSInfo::ExtractFromSource(const Source &pSource,
1297bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao                                  const DependencyTableTy &pDeps)
1301e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang{
1311e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::Module &module = pSource.getModule();
1321e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const char *module_name = module.getModuleIdentifier().c_str();
1331e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1341e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *pragma =
1351e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(pragma_metadata_name);
1361e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *export_var =
1371e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(export_var_metadata_name);
1381e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *export_func =
1391e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(export_func_metadata_name);
1401e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *export_foreach_name =
1411e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(export_foreach_name_metadata_name);
1421e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *export_foreach_signature =
1431e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(export_foreach_metadata_name);
1441e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  const llvm::NamedMDNode *object_slots =
1451e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      module.getNamedMetadata(object_slot_metadata_name);
1461e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1471e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Always write a byte 0x0 at the beginning of the string pool.
1481e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  size_t string_pool_size = 1;
1491e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  off_t cur_string_pool_offset = 0;
1501e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1511e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  RSInfo *result = NULL;
1521e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1531e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
1541e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // section for ForEach. We generate a full signature for a "root" function.
1551e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if ((export_foreach_name == NULL) || (export_foreach_signature == NULL)) {
1561e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    export_foreach_name = NULL;
1571e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    export_foreach_signature = NULL;
1581e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    string_pool_size += 5;  // insert "root\0" for #rs_export_foreach_name
1591e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
1601e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1611e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  string_pool_size += getMetadataStringLength<2>(pragma);
1621e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  string_pool_size += getMetadataStringLength<1>(export_var);
1631e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  string_pool_size += getMetadataStringLength<1>(export_func);
1641e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  string_pool_size += getMetadataStringLength<1>(export_foreach_name);
1651e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1661e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Don't forget to reserve the space for the dependency informationin string
1671e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // pool.
168f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  string_pool_size += ::strlen(LibBCCPath) + 1 + SHA1_DIGEST_LENGTH;
169f290793bc65b8483332ac8b568962395c4a63927Zonr Chang  string_pool_size += ::strlen(LibRSPath) + 1 + SHA1_DIGEST_LENGTH;
1702665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao  string_pool_size += ::strlen(LibCLCorePath) + 1 + SHA1_DIGEST_LENGTH;
171b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao#if defined(ARCH_ARM_HAVE_NEON)
172b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao  string_pool_size += ::strlen(LibCLCoreNEONPath) + 1 + SHA1_DIGEST_LENGTH;
173b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao#endif
1741e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  for (unsigned i = 0, e = pDeps.size(); i != e; i++) {
1757bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao    // +1 for null-terminator
1767bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao    string_pool_size += ::strlen(/* name */pDeps[i].first) + 1;
1777bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao    // +SHA1_DIGEST_LENGTH for SHA-1 checksum
1787bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao    string_pool_size += SHA1_DIGEST_LENGTH;
1791e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
1801e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1811e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Allocate result object
1821e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  result = new (std::nothrow) RSInfo(string_pool_size);
1831e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (result == NULL) {
1841e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    ALOGE("Out of memory when create RSInfo object for %s!", module_name);
1851e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    goto bail;
1861e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
1871e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1881e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Check string pool.
1891e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (result->mStringPool == NULL) {
1901e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    ALOGE("Out of memory when allocate string pool in RSInfo object for %s!",
1911e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          module_name);
1921e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    goto bail;
1931e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
1941e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1951e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // First byte of string pool should be an empty string
1961e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  result->mStringPool[ cur_string_pool_offset++ ] = '\0';
1971e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
1981e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Populate all the strings and data.
1991e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang#define FOR_EACH_NODE_IN(_metadata, _node)  \
2001e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  for (unsigned i = 0, e = (_metadata)->getNumOperands(); i != e; i++)  \
2011e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    if (((_node) = (_metadata)->getOperand(i)) != NULL)
2021e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2031e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #pragma
2041e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2051e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Pragma is actually a key-value pair. The value can be an empty string while
2061e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // the key cannot.
2071e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (pragma != NULL) {
2081e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    llvm::MDNode *node;
2091e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    FOR_EACH_NODE_IN(pragma, node) {
2101e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        llvm::StringRef key = getStringFromOperand(node->getOperand(0));
2111e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        llvm::StringRef val = getStringFromOperand(node->getOperand(1));
2121e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        if (key.empty()) {
2131e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          ALOGW("%s contains pragma metadata with empty key (skip)!",
2141e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                module_name);
2151e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        } else {
2161e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          result->mPragmas.push(std::make_pair(
2171e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              writeString(key, result->mStringPool, &cur_string_pool_offset),
2181e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              writeString(val, result->mStringPool, &cur_string_pool_offset)));
2191e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        } // key.empty()
2201e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    } // FOR_EACH_NODE_IN
2211e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  } // pragma != NULL
2221e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2231e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2241e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_export_var
2251e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2261e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (export_var != NULL) {
2271e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    llvm::MDNode *node;
2281e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    FOR_EACH_NODE_IN(export_var, node) {
2291e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::StringRef name = getStringFromOperand(node->getOperand(0));
2301e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (name.empty()) {
2311e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        ALOGW("%s contains empty entry in #rs_export_var metadata (skip)!",
2321e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              module_name);
2331e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      } else {
2341e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          result->mExportVarNames.push(
2351e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              writeString(name, result->mStringPool, &cur_string_pool_offset));
2361e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
2371e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
2381e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
2391e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2401e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2411e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_export_func
2421e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2431e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (export_func != NULL) {
2441e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    llvm::MDNode *node;
2451e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    FOR_EACH_NODE_IN(export_func, node) {
2461e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::StringRef name = getStringFromOperand(node->getOperand(0));
2471e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (name.empty()) {
2481e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        ALOGW("%s contains empty entry in #rs_export_func metadata (skip)!",
2491e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              module_name);
2501e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      } else {
2511e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        result->mExportFuncNames.push(
2521e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang            writeString(name, result->mStringPool, &cur_string_pool_offset));
2531e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
2541e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
2551e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
2561e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2571e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2581e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_export_foreach and #rs_export_foreach_name
2591e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
2601e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // It's a little bit complicated to deal with #rs_export_foreach (the
2611e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // signature of foreach-able function) and #rs_export_foreach_name (the name
2621e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // of function which is foreach-able). We have to maintain a legacy case:
2631e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //
2641e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //  In pre-ICS bitcode, forEach feature only supports non-graphic root()
2651e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //  function and only one signature corresponded to that non-graphic root()
2661e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //  was written to the #rs_export_foreach metadata section. There's no
2671e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //  #rs_export_foreach_name metadata section.
2681e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //
2691e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Currently, not only non-graphic root() is supported but also other
2701e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // functions that are exportable. Therefore, a new metadata section
2711e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_export_foreach_name is added to specify which functions are
2721e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // for-eachable. In this case, #rs_export_foreach (the function name) and
2731e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_export_foreach metadata (the signature) is one-to-one mapping among
2741e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // their entries.
2751e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if ((export_foreach_name != NULL) && (export_foreach_signature != NULL)) {
2761e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    unsigned num_foreach_function;
2771e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2781e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    // Should be one-to-one mapping.
2791e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    if (export_foreach_name->getNumOperands() !=
2801e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        export_foreach_signature->getNumOperands()) {
2811e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      ALOGE("Mismatch number of foreach-able function names (%u) in "
2821e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang            "#rs_export_foreach_name and number of signatures (%u) "
2831e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang            "in %s!", export_foreach_name->getNumOperands(),
2841e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang            export_foreach_signature->getNumOperands(), module_name);
2851e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      goto bail;
2861e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
2871e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2881e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    num_foreach_function = export_foreach_name->getNumOperands();
2891e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    for (unsigned i = 0; i < num_foreach_function; i++) {
2901e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::MDNode *name_node = export_foreach_name->getOperand(i);
2911e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::MDNode *signature_node = export_foreach_signature->getOperand(i);
2921e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
2931e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::StringRef name, signature_string;
2941e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (name_node != NULL) {
2951e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        name = getStringFromOperand(name_node->getOperand(0));
2961e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
2971e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (signature_node != NULL) {
2981e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        signature_string = getStringFromOperand(signature_node->getOperand(0));
2991e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
3001e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3011e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (!name.empty() && !signature_string.empty()) {
3021e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        // Both name_node and signature_node are not NULL nodes.
3031e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        uint32_t signature;
3041e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        if (signature_string.getAsInteger(10, signature)) {
3051e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          ALOGE("Non-integer signature value '%s' for function %s found in %s!",
3061e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                signature_string.str().c_str(), name.str().c_str(), module_name);
3071e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          goto bail;
3081e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        }
3091e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        result->mExportForeachFuncs.push(std::make_pair(
3101e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              writeString(name, result->mStringPool, &cur_string_pool_offset),
3111e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              signature));
3121e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      } else {
3131e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        // One or both of the name and signature value are empty. It's safe only
3141e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        // if both of them are empty.
3151e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        if (name.empty() && signature_string.empty()) {
3161e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          ALOGW("Entries #%u at #rs_export_foreach_name and #rs_export_foreach"
3171e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                " are both NULL in %s! (skip)", i, module_name);
3181e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          continue;
3191e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        } else {
3201e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          ALOGE("Entries #%u at %s is NULL in %s! (skip)", i,
3211e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                (name.empty() ? "#rs_export_foreach_name" :
3221e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                                "#rs_export_foreach"), module_name);
3231e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          goto bail;
3241e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        }
3251e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
3261e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    } // end for
3271e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  } else {
3281e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    // To handle the legacy case, we generate a full signature for a "root"
3291e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    // function which means that we need to set the bottom 5 bits (0x1f) in the
3301e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    // mask.
3311e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    result->mExportForeachFuncs.push(std::make_pair(
3321e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          writeString(llvm::StringRef("root"), result->mStringPool,
3331e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                      &cur_string_pool_offset), 0x1f));
3341e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
3351e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3361e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3371e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // #rs_object_slots
3381e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3391e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (object_slots != NULL) {
3401e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    llvm::MDNode *node;
3416f3138bbc93b7105ddb49a803c15c3f98077f533Stephen Hines    for (unsigned int i = 0; i <= export_var->getNumOperands(); i++) {
3426f3138bbc93b7105ddb49a803c15c3f98077f533Stephen Hines      result->mObjectSlots.push(0);
3436f3138bbc93b7105ddb49a803c15c3f98077f533Stephen Hines    }
3441e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    FOR_EACH_NODE_IN(object_slots, node) {
3451e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      llvm::StringRef val = getStringFromOperand(node->getOperand(0));
3461e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      if (val.empty()) {
3471e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        ALOGW("%s contains empty entry in #rs_object_slots (skip)!",
3481e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang              module.getModuleIdentifier().c_str());
3491e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      } else {
3501e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        uint32_t slot;
3511e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        if (val.getAsInteger(10, slot)) {
3521e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          ALOGE("Non-integer object slot value '%s' in %s!", val.str().c_str(),
3531e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                module.getModuleIdentifier().c_str());
3541e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang          goto bail;
3556f3138bbc93b7105ddb49a803c15c3f98077f533Stephen Hines        } else {
3566f3138bbc93b7105ddb49a803c15c3f98077f533Stephen Hines          result->mObjectSlots.editItemAt(slot) = 1;
3571e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang        }
3581e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      }
3591e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
3601e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
3611e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang#undef FOR_EACH_NODE_IN
3621e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3631e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3641e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Record built-in dependency information.
3651e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3661e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  LoadBuiltInSHA1Information();
3671e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3681e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (!writeDependency(LibBCCPath, LibBCCSHA1,
3691e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                       result->mStringPool, &cur_string_pool_offset,
3701e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                       result->mDependencyTable)) {
3711e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    goto bail;
3721e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
3731e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3741e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  if (!writeDependency(LibRSPath, LibRSSHA1,
3751e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                       result->mStringPool, &cur_string_pool_offset,
3761e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang                       result->mDependencyTable)) {
3771e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    goto bail;
3781e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
3791e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
3802665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao  if (!writeDependency(LibCLCorePath, LibCLCoreSHA1,
3812665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao                       result->mStringPool, &cur_string_pool_offset,
3822665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao                       result->mDependencyTable)) {
3832665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao    goto bail;
3842665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao  }
3852665c2f94ed14c1d15925d83b47aa519a11dafe5Shih-wei Liao
386b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao#if defined(ARCH_ARM_HAVE_NEON)
387b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao  if (!writeDependency(LibCLCoreNEONPath, LibCLCoreNEONSHA1,
388b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao                       result->mStringPool, &cur_string_pool_offset,
389b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao                       result->mDependencyTable)) {
390b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao    goto bail;
391b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao  }
392b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao#endif
393b1cc74f2fc38ea115b69f65302bc62478fe59a4aShih-wei Liao
3941e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3951e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Record dependency information.
3961e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
3971e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  for (unsigned i = 0, e = pDeps.size(); i != e; i++) {
3987bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao    if (!writeDependency(/* name */pDeps[i].first, /* SHA-1 */pDeps[i].second,
3997bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao                         result->mStringPool, &cur_string_pool_offset,
4007bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao                         result->mDependencyTable)) {
4017bcec85228c1eceade6efc9cd7d02ef81c8d55e9Shih-wei Liao      goto bail;
4021e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang    }
4031e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  }
4041e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
4051e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
4061e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // Determine whether the bitcode contains debug information
4071e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  //===--------------------------------------------------------------------===//
4081e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // The root context of the debug information in the bitcode is put under
4091e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  // the metadata named "llvm.dbg.cu".
4101e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  result->mHeader.hasDebugInformation =
4111e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang      static_cast<uint8_t>(module.getNamedMetadata("llvm.dbg.cu") != NULL);
4121e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
4131e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  assert((cur_string_pool_offset == string_pool_size) &&
4141e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang            "Unexpected string pool size!");
4151e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
4161e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return result;
4171e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang
4181e2adce6df4414d827149ec563c9c89f21ea7426Zonr Changbail:
4191e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  delete result;
4201e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang  return NULL;
4211e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang}
422