/*
 * Copyright 2011-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.
 */

#include "bcinfo/MetadataExtractor.h"

#include "bcinfo/BitcodeWrapper.h"
#include "rsDefines.h"

#define LOG_TAG "bcinfo"
#include <cutils/log.h>
#ifdef __ANDROID__
#include <cutils/properties.h>
#endif

#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/MemoryBuffer.h"

#include <cstdlib>

namespace bcinfo {

namespace {

llvm::StringRef getStringOperand(const llvm::Metadata *node) {
  if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
    return mds->getString();
  }
  return llvm::StringRef();
}

bool extractUIntFromMetadataString(uint32_t *value,
    const llvm::Metadata *m) {
  llvm::StringRef SigString = getStringOperand(m);
  if (SigString != "") {
    if (!SigString.getAsInteger(10, *value)) {
      return true;
    }
  }
  return false;
}

const char *createStringFromValue(llvm::Metadata *m) {
  auto ref = getStringOperand(m);
  char *c = new char[ref.size() + 1];
  memcpy(c, ref.data(), ref.size());
  c[ref.size()] = '\0';
  return c;
}

const char *createStringFromOptionalValue(llvm::MDNode *n, unsigned opndNum) {
  llvm::Metadata *opnd;
  if (opndNum >= n->getNumOperands() || !(opnd = n->getOperand(opndNum)))
    return nullptr;
  return createStringFromValue(opnd);
}

// Collect metadata from NamedMDNodes that contain a list of names
// (strings).
//
// Inputs:
//
// NamedMetadata - An LLVM metadata node, each of whose operands have
// a string as their first entry
//
// NameList - A reference that will hold an allocated array of strings
//
// Count - A reference that will hold the length of the allocated
// array of strings
//
// Return value:
//
// Return true on success, false on error.
//
// Upon success, the function sets NameList to an array of strings
// corresponding the names found in the metadata. The function sets
// Count to the number of entries in NameList.
//
// An error occurs if one of the metadata operands doesn't have a
// first entry.
bool populateNameMetadata(const llvm::NamedMDNode *NameMetadata,
                          const char **&NameList, size_t &Count) {
  if (!NameMetadata) {
    NameList = nullptr;
    Count = 0;
    return true;
  }

  Count = NameMetadata->getNumOperands();
  if (!Count) {
    NameList = nullptr;
    return true;
  }

  NameList = new const char *[Count];

  for (size_t i = 0; i < Count; i++) {
    llvm::MDNode *Name = NameMetadata->getOperand(i);
    if (Name && Name->getNumOperands() > 0) {
      NameList[i] = createStringFromValue(Name->getOperand(0));
    } else {
      ALOGE("Metadata operand does not contain a name string");
      for (size_t AllocatedIndex = 0; AllocatedIndex < i; AllocatedIndex++) {
        delete [] NameList[AllocatedIndex];
      }
      delete [] NameList;
      NameList = nullptr;
      Count = 0;

      return false;
    }
  }

  return true;
}

} // end anonymous namespace

// Name of metadata node where pragma info resides (should be synced with
// slang.cpp)
static const llvm::StringRef PragmaMetadataName = "#pragma";

// Name of metadata node where exported variable names reside (should be
// synced with slang_rs_metadata.h)
static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";

// Name of metadata node where exported function names reside (should be
// synced with slang_rs_metadata.h)
static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";

// Name of metadata node where exported ForEach name information resides
// (should be synced with slang_rs_metadata.h)
static const llvm::StringRef ExportForEachNameMetadataName =
    "#rs_export_foreach_name";

// Name of metadata node where exported ForEach signature information resides
// (should be synced with slang_rs_metadata.h)
static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";

// Name of metadata node where exported general reduce information resides
// (should be synced with slang_rs_metadata.h)
static const llvm::StringRef ExportReduceMetadataName = "#rs_export_reduce";

// Name of metadata node where RS object slot info resides (should be
// synced with slang_rs_metadata.h)
static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";

static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";

// Name of metadata node where the checksum for this build is stored.  (should
// be synced with libbcc/lib/Core/Source.cpp)
static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";

// Name of metadata node which contains a list of compile units that have debug
// metadata. If this is null then there is no debug metadata in the compile
// unit.
static const llvm::StringRef DebugInfoMetadataName = "llvm.dbg.cu";

MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
    : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
      mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
      mExportReduceCount(0), mExportVarNameList(nullptr),
      mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
      mExportForEachSignatureList(nullptr),
      mExportForEachInputCountList(nullptr),
      mExportReduceList(nullptr),
      mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
      mObjectSlotCount(0), mObjectSlotList(nullptr),
      mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
      mBuildChecksum(nullptr), mHasDebugInfo(false) {
  BitcodeWrapper wrapper(bitcode, bitcodeSize);
  mTargetAPI = wrapper.getTargetAPI();
  mCompilerVersion = wrapper.getCompilerVersion();
  mOptimizationLevel = wrapper.getOptimizationLevel();
}

MetadataExtractor::MetadataExtractor(const llvm::Module *module)
    : mModule(module), mBitcode(nullptr), mBitcodeSize(0),
      mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
      mExportReduceCount(0), mExportVarNameList(nullptr),
      mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
      mExportForEachSignatureList(nullptr),
      mExportForEachInputCountList(nullptr),
      mExportReduceList(nullptr),
      mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
      mObjectSlotCount(0), mObjectSlotList(nullptr),
      mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
      mBuildChecksum(nullptr) {
  mCompilerVersion = RS_VERSION;  // Default to the actual current version.
  mOptimizationLevel = 3;
}


MetadataExtractor::~MetadataExtractor() {
  if (mExportVarNameList) {
    for (size_t i = 0; i < mExportVarCount; i++) {
        delete [] mExportVarNameList[i];
        mExportVarNameList[i] = nullptr;
    }
  }
  delete [] mExportVarNameList;
  mExportVarNameList = nullptr;

  if (mExportFuncNameList) {
    for (size_t i = 0; i < mExportFuncCount; i++) {
        delete [] mExportFuncNameList[i];
        mExportFuncNameList[i] = nullptr;
    }
  }
  delete [] mExportFuncNameList;
  mExportFuncNameList = nullptr;

  if (mExportForEachNameList) {
    for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
        delete [] mExportForEachNameList[i];
        mExportForEachNameList[i] = nullptr;
    }
  }
  delete [] mExportForEachNameList;
  mExportForEachNameList = nullptr;

  delete [] mExportForEachSignatureList;
  mExportForEachSignatureList = nullptr;

  delete [] mExportForEachInputCountList;
  mExportForEachInputCountList = nullptr;

  delete [] mExportReduceList;
  mExportReduceList = nullptr;

  for (size_t i = 0; i < mPragmaCount; i++) {
    if (mPragmaKeyList) {
      delete [] mPragmaKeyList[i];
      mPragmaKeyList[i] = nullptr;
    }
    if (mPragmaValueList) {
      delete [] mPragmaValueList[i];
      mPragmaValueList[i] = nullptr;
    }
  }
  delete [] mPragmaKeyList;
  mPragmaKeyList = nullptr;
  delete [] mPragmaValueList;
  mPragmaValueList = nullptr;

  delete [] mObjectSlotList;
  mObjectSlotList = nullptr;

  delete [] mBuildChecksum;

  return;
}


bool MetadataExtractor::populateObjectSlotMetadata(
    const llvm::NamedMDNode *ObjectSlotMetadata) {
  if (!ObjectSlotMetadata) {
    return true;
  }

  mObjectSlotCount = ObjectSlotMetadata->getNumOperands();

  if (!mObjectSlotCount) {
    return true;
  }

  uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
  memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));

  for (size_t i = 0; i < mObjectSlotCount; i++) {
    llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
    if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
      if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
        ALOGE("Non-integer object slot value");
        return false;
      }
    } else {
      ALOGE("Corrupt object slot information");
      return false;
    }
  }

  mObjectSlotList = TmpSlotList;

  return true;
}


void MetadataExtractor::populatePragmaMetadata(
    const llvm::NamedMDNode *PragmaMetadata) {
  if (!PragmaMetadata) {
    return;
  }

  mPragmaCount = PragmaMetadata->getNumOperands();
  if (!mPragmaCount) {
    return;
  }

  const char **TmpKeyList = new const char*[mPragmaCount];
  const char **TmpValueList = new const char*[mPragmaCount];

  for (size_t i = 0; i < mPragmaCount; i++) {
    llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
    if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
      llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
      TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
      llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
      TmpValueList[i] = createStringFromValue(PragmaValueMDS);
    }
  }

  mPragmaKeyList = TmpKeyList;
  mPragmaValueList = TmpValueList;

  // Check to see if we have any FP precision-related pragmas.
  std::string Relaxed("rs_fp_relaxed");
  std::string Imprecise("rs_fp_imprecise");
  std::string Full("rs_fp_full");
  bool RelaxedPragmaSeen = false;
  bool FullPragmaSeen = false;
  for (size_t i = 0; i < mPragmaCount; i++) {
    if (!Relaxed.compare(mPragmaKeyList[i])) {
      RelaxedPragmaSeen = true;
    } else if (!Imprecise.compare(mPragmaKeyList[i])) {
      ALOGW("rs_fp_imprecise is deprecated.  Assuming rs_fp_relaxed instead.");
      RelaxedPragmaSeen = true;
    } else if (!Full.compare(mPragmaKeyList[i])) {
      FullPragmaSeen = true;
    }
  }

  if (RelaxedPragmaSeen && FullPragmaSeen) {
    ALOGE("Full and relaxed precision specified at the same time!");
  }
  mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;

#ifdef __ANDROID__
  // Provide an override for precsiion via adb shell setprop
  // adb shell setprop debug.rs.precision rs_fp_full
  // adb shell setprop debug.rs.precision rs_fp_relaxed
  // adb shell setprop debug.rs.precision rs_fp_imprecise
  char PrecisionPropBuf[PROPERTY_VALUE_MAX];
  const std::string PrecisionPropName("debug.rs.precision");
  property_get("debug.rs.precision", PrecisionPropBuf, "");
  if (PrecisionPropBuf[0]) {
    if (!Relaxed.compare(PrecisionPropBuf)) {
      ALOGI("Switching to RS FP relaxed mode via setprop");
      mRSFloatPrecision = RS_FP_Relaxed;
    } else if (!Imprecise.compare(PrecisionPropBuf)) {
      ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
            "specified but is deprecated ");
      mRSFloatPrecision = RS_FP_Relaxed;
    } else if (!Full.compare(PrecisionPropBuf)) {
      ALOGI("Switching to RS FP full mode via setprop");
      mRSFloatPrecision = RS_FP_Full;
    } else {
      ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
    }
  }
#endif
}

uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
                                               uint32_t Signature) {

  if (hasForEachSignatureIn(Signature)) {
    uint32_t OtherCount = 0;

    OtherCount += hasForEachSignatureUsrData(Signature);
    OtherCount += hasForEachSignatureX(Signature);
    OtherCount += hasForEachSignatureY(Signature);
    OtherCount += hasForEachSignatureZ(Signature);
    OtherCount += hasForEachSignatureCtxt(Signature);
    OtherCount += hasForEachSignatureOut(Signature) &&
                  Function->getReturnType()->isVoidTy();

    return Function->arg_size() - OtherCount;

  } else {
    return 0;
  }
}


bool MetadataExtractor::populateForEachMetadata(
    const llvm::NamedMDNode *Names,
    const llvm::NamedMDNode *Signatures) {
  if (!Names && !Signatures && mCompilerVersion == 0) {
    // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
    // section for ForEach. We generate a full signature for a "root" function
    // which means that we need to set the bottom 5 bits in the mask.
    mExportForEachSignatureCount = 1;
    char **TmpNameList = new char*[mExportForEachSignatureCount];
    size_t RootLen = strlen(kRoot) + 1;
    TmpNameList[0] = new char[RootLen];
    strncpy(TmpNameList[0], kRoot, RootLen);

    uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
    TmpSigList[0] = 0x1f;

    mExportForEachNameList = (const char**)TmpNameList;
    mExportForEachSignatureList = TmpSigList;
    return true;
  }

  if (Signatures) {
    mExportForEachSignatureCount = Signatures->getNumOperands();
    if (!mExportForEachSignatureCount) {
      return true;
    }
  } else {
    mExportForEachSignatureCount = 0;
    mExportForEachSignatureList = nullptr;
    return true;
  }

  uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
  const char **TmpNameList = new const char*[mExportForEachSignatureCount];
  uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];

  for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
    llvm::MDNode *SigNode = Signatures->getOperand(i);
    if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
      if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
        ALOGE("Non-integer signature value");
        return false;
      }
    } else {
      ALOGE("Corrupt signature information");
      return false;
    }
  }

  if (Names) {
    for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
      llvm::MDNode *Name = Names->getOperand(i);
      if (Name != nullptr && Name->getNumOperands() == 1) {
        TmpNameList[i] = createStringFromValue(Name->getOperand(0));

        // Note that looking up the function by name can fail: One of
        // the uses of MetadataExtractor is as part of the
        // RSEmbedInfoPass, which bcc_compat runs sufficiently late in
        // the phase order that RSKernelExpandPass has already run and
        // the original (UNexpanded) kernel function (TmpNameList[i])
        // may have been deleted as having no references (if it has
        // been inlined into the expanded kernel function and is
        // otherwise unreferenced).
        llvm::Function *Func =
            mModule->getFunction(llvm::StringRef(TmpNameList[i]));

        TmpInputCountList[i] = (Func != nullptr) ?
          calculateNumInputs(Func, TmpSigList[i]) : 0;
      }
    }
  } else {
    if (mExportForEachSignatureCount != 1) {
      ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
            mExportForEachSignatureCount);
    }
    char *RootName = new char[5];
    strncpy(RootName, "root", 5);
    TmpNameList[0] = RootName;
  }

  mExportForEachNameList = TmpNameList;
  mExportForEachSignatureList = TmpSigList;
  mExportForEachInputCountList = TmpInputCountList;

  return true;
}


bool MetadataExtractor::populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata) {
  mExportReduceCount = 0;
  mExportReduceList = nullptr;

  if (!ReduceMetadata || !(mExportReduceCount = ReduceMetadata->getNumOperands()))
    return true;

  Reduce *TmpReduceList = new Reduce[mExportReduceCount];

  for (size_t i = 0; i < mExportReduceCount; i++) {
    llvm::MDNode *Node = ReduceMetadata->getOperand(i);
    if (!Node || Node->getNumOperands() < 3) {
      ALOGE("Missing reduce metadata");
      return false;
    }

    TmpReduceList[i].mReduceName = createStringFromValue(Node->getOperand(0));

    if (!extractUIntFromMetadataString(&TmpReduceList[i].mAccumulatorDataSize,
                                       Node->getOperand(1))) {
      ALOGE("Non-integer accumulator data size value in reduce metadata");
      return false;
    }

    llvm::MDNode *AccumulatorNode = llvm::dyn_cast<llvm::MDNode>(Node->getOperand(2));
    if (!AccumulatorNode || AccumulatorNode->getNumOperands() != 2) {
      ALOGE("Malformed accumulator node in reduce metadata");
      return false;
    }
    TmpReduceList[i].mAccumulatorName = createStringFromValue(AccumulatorNode->getOperand(0));
    if (!extractUIntFromMetadataString(&TmpReduceList[i].mSignature,
                                       AccumulatorNode->getOperand(1))) {
      ALOGE("Non-integer signature value in reduce metadata");
      return false;
    }
    // Note that looking up the function by name can fail: One of the
    // uses of MetadataExtractor is as part of the RSEmbedInfoPass,
    // which bcc_compat runs sufficiently late in the phase order that
    // RSKernelExpandPass has already run and the original
    // (UNexpanded) accumulator function (mAccumulatorName) may have
    // been deleted as having no references (if it has been inlined
    // into the expanded accumulator function and is otherwise
    // unreferenced).
    llvm::Function *Func =
        mModule->getFunction(llvm::StringRef(TmpReduceList[i].mAccumulatorName));
    // Why calculateNumInputs() - 1?  The "-1" is because we don't
    // want to treat the accumulator argument as an input.
    TmpReduceList[i].mInputCount = (Func ? calculateNumInputs(Func, TmpReduceList[i].mSignature) - 1 : 0);

    TmpReduceList[i].mInitializerName = createStringFromOptionalValue(Node, 3);
    TmpReduceList[i].mCombinerName = createStringFromOptionalValue(Node, 4);
    TmpReduceList[i].mOutConverterName = createStringFromOptionalValue(Node, 5);
    TmpReduceList[i].mHalterName = createStringFromOptionalValue(Node, 6);
  }

  mExportReduceList = TmpReduceList;
  return true;
}

void MetadataExtractor::readThreadableFlag(
    const llvm::NamedMDNode *ThreadableMetadata) {

  // Scripts are threadable by default.  If we read a valid metadata value for
  // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
  // threadable.  All other exception paths retain the default value.

  mIsThreadable = true;
  if (ThreadableMetadata == nullptr)
    return;

  llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
  if (mdNode == nullptr)
    return;

  llvm::Metadata *mdValue = mdNode->getOperand(0);
  if (mdValue == nullptr)
    return;

  if (getStringOperand(mdValue) == "no")
    mIsThreadable = false;
}

void MetadataExtractor::readBuildChecksumMetadata(
    const llvm::NamedMDNode *ChecksumMetadata) {

  if (ChecksumMetadata == nullptr)
    return;

  llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
  if (mdNode == nullptr)
    return;

  llvm::Metadata *mdValue = mdNode->getOperand(0);
  if (mdValue == nullptr)
    return;

  mBuildChecksum = createStringFromValue(mdValue);
}

bool MetadataExtractor::extract() {
  if (!(mBitcode && mBitcodeSize) && !mModule) {
    ALOGE("Invalid/empty bitcode/module");
    return false;
  }

  std::unique_ptr<llvm::LLVMContext> mContext;
  bool shouldNullModule = false;

  if (!mModule) {
    mContext.reset(new llvm::LLVMContext());
    std::unique_ptr<llvm::MemoryBuffer> MEM(
      llvm::MemoryBuffer::getMemBuffer(
        llvm::StringRef(mBitcode, mBitcodeSize), "", false));
    std::string error;

    llvm::ErrorOr<std::unique_ptr<llvm::Module> > errval =
        llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(), *mContext);
    if (std::error_code ec = errval.getError()) {
        ALOGE("Could not parse bitcode file");
        ALOGE("%s", ec.message().c_str());
        return false;
    }

    mModule = errval.get().release();
    shouldNullModule = true;
  }

  const llvm::NamedMDNode *ExportVarMetadata =
      mModule->getNamedMetadata(ExportVarMetadataName);
  const llvm::NamedMDNode *ExportFuncMetadata =
      mModule->getNamedMetadata(ExportFuncMetadataName);
  const llvm::NamedMDNode *ExportForEachNameMetadata =
      mModule->getNamedMetadata(ExportForEachNameMetadataName);
  const llvm::NamedMDNode *ExportForEachMetadata =
      mModule->getNamedMetadata(ExportForEachMetadataName);
  const llvm::NamedMDNode *ExportReduceMetadata =
      mModule->getNamedMetadata(ExportReduceMetadataName);
  const llvm::NamedMDNode *PragmaMetadata =
      mModule->getNamedMetadata(PragmaMetadataName);
  const llvm::NamedMDNode *ObjectSlotMetadata =
      mModule->getNamedMetadata(ObjectSlotMetadataName);
  const llvm::NamedMDNode *ThreadableMetadata =
      mModule->getNamedMetadata(ThreadableMetadataName);
  const llvm::NamedMDNode *ChecksumMetadata =
      mModule->getNamedMetadata(ChecksumMetadataName);
  const llvm::NamedMDNode *DebugInfoMetadata =
      mModule->getNamedMetadata(DebugInfoMetadataName);

  if (!populateNameMetadata(ExportVarMetadata, mExportVarNameList,
                            mExportVarCount)) {
    ALOGE("Could not populate export variable metadata");
    goto err;
  }

  if (!populateNameMetadata(ExportFuncMetadata, mExportFuncNameList,
                            mExportFuncCount)) {
    ALOGE("Could not populate export function metadata");
    goto err;
  }

  if (!populateForEachMetadata(ExportForEachNameMetadata,
                               ExportForEachMetadata)) {
    ALOGE("Could not populate ForEach signature metadata");
    goto err;
  }

  if (!populateReduceMetadata(ExportReduceMetadata)) {
    ALOGE("Could not populate export general reduction metadata");
    goto err;
  }

  populatePragmaMetadata(PragmaMetadata);

  if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
    ALOGE("Could not populate object slot metadata");
    goto err;
  }

  readThreadableFlag(ThreadableMetadata);
  readBuildChecksumMetadata(ChecksumMetadata);

  mHasDebugInfo = DebugInfoMetadata != nullptr;

  if (shouldNullModule) {
    mModule = nullptr;
  }
  return true;

err:
  if (shouldNullModule) {
    mModule = nullptr;
  }
  return false;
}

}  // namespace bcinfo
