/*
 * 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"

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

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

#include <cstdlib>

namespace bcinfo {

// 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 RS object slot info resides (should be
// synced with slang_rs_metadata.h)
static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";


MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
    : mModule(NULL), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
      mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
      mExportVarNameList(NULL), mExportFuncNameList(NULL),
      mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
      mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
      mObjectSlotCount(0), mObjectSlotList(NULL),
      mRSFloatPrecision(RS_FP_Full) {
  BitcodeWrapper wrapper(bitcode, bitcodeSize);
  mCompilerVersion = wrapper.getCompilerVersion();
  mOptimizationLevel = wrapper.getOptimizationLevel();
}


MetadataExtractor::MetadataExtractor(const llvm::Module *module)
    : mModule(module), mBitcode(NULL), mBitcodeSize(0), mExportVarCount(0),
      mExportFuncCount(0), mExportForEachSignatureCount(0),
      mExportVarNameList(NULL), mExportFuncNameList(NULL),
      mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
      mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
      mObjectSlotCount(0), mObjectSlotList(NULL),
      mRSFloatPrecision(RS_FP_Full) {
  mCompilerVersion = 0;
  mOptimizationLevel = 3;
}


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

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

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

  delete [] mExportForEachSignatureList;
  mExportForEachSignatureList = NULL;

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

  delete [] mObjectSlotList;
  mObjectSlotList = NULL;

  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 != NULL && ObjectSlot->getNumOperands() == 1) {
      llvm::Value *SlotMDS = ObjectSlot->getOperand(0);
      if (SlotMDS->getValueID() == llvm::Value::MDStringVal) {
        llvm::StringRef Slot =
            static_cast<llvm::MDString*>(SlotMDS)->getString();
        uint32_t USlot = 0;
        if (Slot.getAsInteger(10, USlot)) {
          ALOGE("Non-integer object slot value '%s'", Slot.str().c_str());
          return false;
        }
        TmpSlotList[i] = USlot;
      }
    }
  }

  mObjectSlotList = TmpSlotList;

  return true;
}


static const char *createStringFromValue(llvm::Value *v) {
  if (v->getValueID() != llvm::Value::MDStringVal) {
    return NULL;
  }

  llvm::StringRef ref = static_cast<llvm::MDString*>(v)->getString();

  char *c = new char[ref.size() + 1];
  memcpy(c, ref.data(), ref.size());
  c[ref.size()] = '\0';

  return c;
}


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 != NULL && Pragma->getNumOperands() == 2) {
      llvm::Value *PragmaKeyMDS = Pragma->getOperand(0);
      TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
      llvm::Value *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 ImprecisePragmaSeen = false;

  for (size_t i = 0; i < mPragmaCount; i++) {
    if (!Relaxed.compare(mPragmaKeyList[i])) {
      if (RelaxedPragmaSeen || ImprecisePragmaSeen) {
        ALOGE("Multiple float precision pragmas specified!");
      }
      RelaxedPragmaSeen = true;
    } else if (!Imprecise.compare(mPragmaKeyList[i])) {
      if (RelaxedPragmaSeen || ImprecisePragmaSeen) {
        ALOGE("Multiple float precision pragmas specified!");
      }
      ImprecisePragmaSeen = true;
    }
  }

  // Imprecise is selected over Relaxed precision.
  // In the absence of both, we stick to the default Full precision.
  if (ImprecisePragmaSeen) {
    mRSFloatPrecision = RS_FP_Imprecise;
  } else if (RelaxedPragmaSeen) {
    mRSFloatPrecision = RS_FP_Relaxed;
  }

  // Provide an override for precsion 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)) {
      ALOGE("Switching to RS FP relaxed mode via setprop");
      mRSFloatPrecision = RS_FP_Relaxed;
    } else if (!Imprecise.compare(PrecisionPropBuf)) {
      ALOGE("Switching to RS FP imprecise mode via setprop");
      mRSFloatPrecision = RS_FP_Imprecise;
    } else if (!Full.compare(PrecisionPropBuf)) {
      ALOGE("Switching to RS FP full mode via setprop");
      mRSFloatPrecision = RS_FP_Full;
    }
  }

  return;
}


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

  mExportVarCount = VarNameMetadata->getNumOperands();
  if (!mExportVarCount) {
    return true;
  }

  const char **TmpNameList = new const char *[mExportVarCount];

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

  mExportVarNameList = TmpNameList;

  return true;
}


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

  mExportFuncCount = FuncNameMetadata->getNumOperands();
  if (!mExportFuncCount) {
    return true;
  }

  const char **TmpNameList = new const char*[mExportFuncCount];

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

  mExportFuncNameList = TmpNameList;

  return true;
}


bool MetadataExtractor::populateForEachMetadata(
    const llvm::NamedMDNode *Names,
    const llvm::NamedMDNode *Signatures) {
  if (!Names && !Signatures) {
    // 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];
    TmpNameList[0] = new char[5];
    strncpy(TmpNameList[0], "root", 5);

    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 = NULL;
    return true;
  }

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

  for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
    llvm::MDNode *SigNode = Signatures->getOperand(i);
    if (SigNode != NULL && SigNode->getNumOperands() == 1) {
      llvm::Value *SigVal = SigNode->getOperand(0);
      if (SigVal->getValueID() == llvm::Value::MDStringVal) {
        llvm::StringRef SigString =
            static_cast<llvm::MDString*>(SigVal)->getString();
        uint32_t Signature = 0;
        if (SigString.getAsInteger(10, Signature)) {
          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
          return false;
        }
        TmpSigList[i] = Signature;
      }
    }
  }

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

  return true;
}


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

  llvm::OwningPtr<llvm::LLVMContext> mContext;

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

    // Module ownership is handled by the context, so we don't need to free it.
    mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &error);
    if (!mModule) {
      ALOGE("Could not parse bitcode file");
      ALOGE("%s", error.c_str());
      return false;
    }
  }

  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 *PragmaMetadata =
      mModule->getNamedMetadata(PragmaMetadataName);
  const llvm::NamedMDNode *ObjectSlotMetadata =
      mModule->getNamedMetadata(ObjectSlotMetadataName);


  if (!populateVarNameMetadata(ExportVarMetadata)) {
    ALOGE("Could not populate export variable metadata");
    return false;
  }

  if (!populateFuncNameMetadata(ExportFuncMetadata)) {
    ALOGE("Could not populate export function metadata");
    return false;
  }

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

  populatePragmaMetadata(PragmaMetadata);

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

  return true;
}

}  // namespace bcinfo

