/*
 * Copyright 2010, 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 "slang_rs_metadata_spec.h"

#include <cstdlib>
#include <list>
#include <map>
#include <string>

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"

#include "llvm/Metadata.h"
#include "llvm/Module.h"

#include "slang_rs_type_spec.h"

#define RS_METADATA_STRTAB_MN   "#rs_metadata_strtab"
#define RS_TYPE_INFO_MN         "#rs_type_info"
#define RS_EXPORT_VAR_MN        "#rs_export_var"
#define RS_EXPORT_FUNC_MN       "#rs_export_func"
#define RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX  "%"

///////////////////////////////////////////////////////////////////////////////
// Useful utility functions
///////////////////////////////////////////////////////////////////////////////
static bool EncodeInteger(llvm::LLVMContext &C,
                          unsigned I,
                          llvm::SmallVectorImpl<llvm::Value*> &Op) {
  llvm::StringRef S(reinterpret_cast<const char*>(&I), sizeof(I));
  llvm::MDString *MDS = llvm::MDString::get(C, S);

  if (MDS == NULL)
    return false;
  Op.push_back(MDS);
  return true;
}

///////////////////////////////////////////////////////////////////////////////
// class RSMetadataEncoderInternal
///////////////////////////////////////////////////////////////////////////////
namespace {

class RSMetadataEncoderInternal {
 private:
  llvm::Module *mModule;

  typedef std::map</* key */unsigned, unsigned/* index */> TypesMapTy;
  TypesMapTy mTypes;
  std::list<unsigned> mEncodedRSTypeInfo;  // simply a sequece of integers
  unsigned mCurTypeIndex;

  // A special type for lookup created record type. It uses record name as key.
  typedef std::map</* name */std::string, unsigned/* index */> RecordTypesMapTy;
  RecordTypesMapTy mRecordTypes;

  typedef std::map<std::string, unsigned/* index */> StringsMapTy;
  StringsMapTy mStrings;
  std::list<const char*> mEncodedStrings;
  unsigned mCurStringIndex;

  llvm::NamedMDNode *mVarInfoMetadata;
  llvm::NamedMDNode *mFuncInfoMetadata;

  // This function check the return value of function:
  //   joinString, encodeTypeBase, encode*Type(), encodeRSType, encodeRSVar,
  //   and encodeRSFunc. Return false if the value of Index indicates failure.
  inline bool checkReturnIndex(unsigned *Index) {
    if (*Index == 0)
      return false;
    else
      (*Index)--;
    return true;
  }

  unsigned joinString(const std::string &S);

  unsigned encodeTypeBase(const struct RSTypeBase *Base);
  unsigned encodeTypeBaseAsKey(const struct RSTypeBase *Base);
#define ENUM_RS_DATA_TYPE_CLASS(x)  \
  unsigned encode ## x ## Type(const union RSType *T);
RS_DATA_TYPE_CLASS_ENUMS
#undef ENUM_RS_DATA_TYPE_CLASS

  unsigned encodeRSType(const union RSType *T);

  int flushStringTable();
  int flushTypeInfo();

 public:
  explicit RSMetadataEncoderInternal(llvm::Module *M);

  int encodeRSVar(const RSVar *V);
  int encodeRSFunc(const RSFunction *F);

  int finalize();
};
}

RSMetadataEncoderInternal::RSMetadataEncoderInternal(llvm::Module *M)
    : mModule(M),
      mCurTypeIndex(0),
      mCurStringIndex(0),
      mVarInfoMetadata(NULL),
      mFuncInfoMetadata(NULL) {
  mTypes.clear();
  mEncodedRSTypeInfo.clear();
  mRecordTypes.clear();
  mStrings.clear();

  return;
}

// Return (StringIndex + 1) when successfully join the string and 0 if there's
// any error.
unsigned RSMetadataEncoderInternal::joinString(const std::string &S) {
  StringsMapTy::const_iterator I = mStrings.find(S);

  if (I != mStrings.end())
    return (I->second + 1);

  // Add S into mStrings
  std::pair<StringsMapTy::iterator, bool> Res =
      mStrings.insert(std::make_pair(S, mCurStringIndex));
  // Insertion failed
  if (!Res.second)
    return 0;

  // Add S into mEncodedStrings
  mEncodedStrings.push_back(Res.first->first.c_str());
  mCurStringIndex++;

  // Return (StringIndex + 1)
  return (Res.first->second + 1);
}

unsigned
RSMetadataEncoderInternal::encodeTypeBase(const struct RSTypeBase *Base) {
  mEncodedRSTypeInfo.push_back(Base->bits);
  return ++mCurTypeIndex;
}

unsigned RSMetadataEncoderInternal::encodeTypeBaseAsKey(
    const struct RSTypeBase *Base) {
  TypesMapTy::const_iterator I = mTypes.find(Base->bits);
  if (I != mTypes.end())
    return (I->second + 1);

  // Add Base into mTypes
  std::pair<TypesMapTy::iterator, bool> Res =
      mTypes.insert(std::make_pair(Base->bits, mCurTypeIndex));
  // Insertion failed
  if (!Res.second)
    return 0;

  // Push to mEncodedRSTypeInfo. This will also update mCurTypeIndex.
  return encodeTypeBase(Base);
}

unsigned RSMetadataEncoderInternal::encodePrimitiveType(const union RSType *T) {
  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
}

unsigned RSMetadataEncoderInternal::encodePointerType(const union RSType *T) {
  // Encode pointee type first
  unsigned PointeeType = encodeRSType(RS_POINTER_TYPE_GET_POINTEE_TYPE(T));
  if (!checkReturnIndex(&PointeeType))
    return 0;

  unsigned Res = encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
  // Push PointeeType after the base type
  mEncodedRSTypeInfo.push_back(PointeeType);
  return Res;
}

unsigned RSMetadataEncoderInternal::encodeVectorType(const union RSType *T) {
  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
}

unsigned RSMetadataEncoderInternal::encodeMatrixType(const union RSType *T) {
  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
}

unsigned
RSMetadataEncoderInternal::encodeConstantArrayType(const union RSType *T) {
  // Encode element type
  unsigned ElementType =
      encodeRSType(RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(T));
  if (!checkReturnIndex(&ElementType))
    return 0;

  unsigned Res = encodeTypeBase(RS_GET_TYPE_BASE(T));
  // Push the ElementType after the type base
  mEncodedRSTypeInfo.push_back(ElementType);
  return Res;
}

unsigned RSMetadataEncoderInternal::encodeRecordType(const union RSType *T) {
  // Construct record name
  std::string RecordInfoMetadataName(RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX);
  RecordInfoMetadataName.append(RS_RECORD_TYPE_GET_NAME(T));

  // Try to find it in mRecordTypes
  RecordTypesMapTy::const_iterator I =
      mRecordTypes.find(RecordInfoMetadataName);

  // This record type has been encoded before. Fast return its index here.
  if (I != mRecordTypes.end())
    return (I->second + 1);

  // Encode this record type into mTypes. Encode record name string first.
  unsigned RecordName = joinString(RecordInfoMetadataName);
  if (!checkReturnIndex(&RecordName))
    return 0;

  unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
  if (!checkReturnIndex(&Base))
    return 0;

  // Push record name after encoding the type base
  mEncodedRSTypeInfo.push_back(RecordName);

  // Add this record type into the map
  std::pair<StringsMapTy::iterator, bool> Res =
      mRecordTypes.insert(std::make_pair(RecordInfoMetadataName, Base));
  // Insertion failed
  if (!Res.second)
    return 0;

  // Create a named MDNode for this record type. We cannot create this before
  // encoding type base into Types and updating mRecordTypes. This is because
  // we may have structure like:
  //
  //            struct foo {
  //              ...
  //              struct foo *bar;  // self type reference
  //              ...
  //            }
  llvm::NamedMDNode *RecordInfoMetadata =
      mModule->getOrInsertNamedMetadata(RecordInfoMetadataName);

  assert((RecordInfoMetadata->getNumOperands() == 0) &&
         "Record created before!");

  // Encode field info into this named MDNode
  llvm::SmallVector<llvm::Value*, 3> FieldInfo;

  for (unsigned i = 0; i < RS_RECORD_TYPE_GET_NUM_FIELDS(T); i++) {
    // 1. field name
    unsigned FieldName = joinString(RS_RECORD_TYPE_GET_FIELD_NAME(T, i));
    if (!checkReturnIndex(&FieldName))
      return 0;
    if (!EncodeInteger(mModule->getContext(),
                       FieldName,
                       FieldInfo))
      return 0;

    // 2. field type
    unsigned FieldType = encodeRSType(RS_RECORD_TYPE_GET_FIELD_TYPE(T, i));
    if (!checkReturnIndex(&FieldType))
      return 0;
    if (!EncodeInteger(mModule->getContext(),
                       FieldType,
                       FieldInfo))
      return 0;

    // 3. field data kind
    if (!EncodeInteger(mModule->getContext(),
                       RS_RECORD_TYPE_GET_FIELD_DATA_KIND(T, i),
                       FieldInfo))
      return 0;

    RecordInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
                                                     FieldInfo.data(),
                                                     FieldInfo.size()));
    FieldInfo.clear();
  }

  return (Res.first->second + 1);
}

unsigned RSMetadataEncoderInternal::encodeRSType(const union RSType *T) {
  switch (static_cast<enum RSTypeClass>(RS_TYPE_GET_CLASS(T))) {
#define ENUM_RS_DATA_TYPE_CLASS(x)  \
    case RS_TC_ ## x: return encode ## x ## Type(T);
    RS_DATA_TYPE_CLASS_ENUMS
#undef ENUM_RS_DATA_TYPE_CLASS
    default: return 0;
  }
  return 0;
}

int RSMetadataEncoderInternal::encodeRSVar(const RSVar *V) {
  // check parameter
  if ((V == NULL) || (V->name == NULL) || (V->type == NULL))
    return -1;

  // 1. var name
  unsigned VarName = joinString(V->name);
  if (!checkReturnIndex(&VarName))
    return -2;

  // 2. type
  unsigned Type = encodeRSType(V->type);

  llvm::SmallVector<llvm::Value*, 1> VarInfo;

  if (!EncodeInteger(mModule->getContext(), VarName, VarInfo))
    return -3;
  if (!EncodeInteger(mModule->getContext(), Type, VarInfo))
    return -4;

  if (mVarInfoMetadata == NULL)
    mVarInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);

  mVarInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
                                                 VarInfo.data(),
                                                 VarInfo.size()));

  return 0;
}

int RSMetadataEncoderInternal::encodeRSFunc(const RSFunction *F) {
  // check parameter
  if ((F == NULL) || (F->name == NULL))
    return -1;

  // 1. var name
  unsigned FuncName = joinString(F->name);
  if (!checkReturnIndex(&FuncName))
    return -2;

  llvm::SmallVector<llvm::Value*, 1> FuncInfo;
  if (!EncodeInteger(mModule->getContext(), FuncName, FuncInfo))
    return -3;

  if (mFuncInfoMetadata == NULL)
    mFuncInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);

  mFuncInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
                                                  FuncInfo.data(),
                                                  FuncInfo.size()));

  return 0;
}

// Write string table and string index table
int RSMetadataEncoderInternal::flushStringTable() {
  assert((mCurStringIndex == mEncodedStrings.size()));
  assert((mCurStringIndex == mStrings.size()));

  if (mCurStringIndex == 0)
    return 0;

  // Prepare named MDNode for string table and string index table.
  llvm::NamedMDNode *RSMetadataStrTab =
      mModule->getOrInsertNamedMetadata(RS_METADATA_STRTAB_MN);
  RSMetadataStrTab->dropAllReferences();

  unsigned StrTabSize = 0;
  unsigned *StrIdx = reinterpret_cast<unsigned*>(
                        ::malloc((mStrings.size() + 1) * sizeof(unsigned)));

  if (StrIdx == NULL)
    return -1;

  unsigned StrIdxI = 0;  // iterator for array StrIdx

  // count StrTabSize and fill StrIdx by the way
  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
          E = mEncodedStrings.end();
       I != E;
       I++) {
    StrIdx[StrIdxI++] = StrTabSize;
    StrTabSize += ::strlen(*I) + 1 /* for '\0' */;
  }
  StrIdx[StrIdxI] = StrTabSize;

  // Allocate
  char *StrTab = reinterpret_cast<char*>(::malloc(StrTabSize));
  if (StrTab == NULL) {
    free(StrIdx);
    return -1;
  }

  llvm::StringRef StrTabData(StrTab, StrTabSize);
  llvm::StringRef StrIdxData(reinterpret_cast<const char*>(StrIdx),
                             mStrings.size() * sizeof(unsigned));

  // Copy
  StrIdxI = 1;
  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
          E = mEncodedStrings.end();
       I != E;
       I++) {
    // Get string length from StrIdx (O(1)) instead of call strlen again (O(n)).
    unsigned CurStrLength = StrIdx[StrIdxI] - StrIdx[StrIdxI - 1];
    ::memcpy(StrTab, *I, CurStrLength);
    // Move forward the pointer
    StrTab += CurStrLength;
    StrIdxI++;
  }

  // Flush to metadata
  llvm::Value *StrTabMDS =
      llvm::MDString::get(mModule->getContext(), StrTabData);
  llvm::Value *StrIdxMDS =
      llvm::MDString::get(mModule->getContext(), StrIdxData);

  if ((StrTabMDS == NULL) || (StrIdxMDS == NULL)) {
    free(StrIdx);
    free(StrTab);
    return -1;
  }

  llvm::SmallVector<llvm::Value*, 2> StrTabVal;
  StrTabVal.push_back(StrTabMDS);
  StrTabVal.push_back(StrIdxMDS);
  RSMetadataStrTab->addOperand(llvm::MDNode::get(mModule->getContext(),
                                                 StrTabVal.data(),
                                                 StrTabVal.size()));

  return 0;
}

// Write RS type stream
int RSMetadataEncoderInternal::flushTypeInfo() {
  unsigned TypeInfoCount = mEncodedRSTypeInfo.size();
  if (TypeInfoCount <= 0)
    return 0;

  llvm::NamedMDNode *RSTypeInfo =
      mModule->getOrInsertNamedMetadata(RS_TYPE_INFO_MN);
  RSTypeInfo->dropAllReferences();

  unsigned *TypeInfos =
      reinterpret_cast<unsigned*>(::malloc(TypeInfoCount * sizeof(unsigned)));
  unsigned TypeInfosIdx = 0;  // iterator for array TypeInfos

  if (TypeInfos == NULL)
    return -1;

  for (std::list<unsigned>::const_iterator I = mEncodedRSTypeInfo.begin(),
          E = mEncodedRSTypeInfo.end();
       I != E;
       I++)
    TypeInfos[TypeInfosIdx++] = *I;

  llvm::StringRef TypeInfoData(reinterpret_cast<const char*>(TypeInfos),
                               TypeInfoCount * sizeof(unsigned));
  llvm::Value *TypeInfoMDS =
      llvm::MDString::get(mModule->getContext(), TypeInfoData);
  if (TypeInfoMDS == NULL) {
    free(TypeInfos);
    return -1;
  }

  RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
                                           &TypeInfoMDS, 1));
  free(TypeInfos);

  return 0;
}

int RSMetadataEncoderInternal::finalize() {
  int Res = flushStringTable();
  if (Res != 0)
    return Res;

  Res = flushTypeInfo();
  if (Res != 0)
    return Res;

  return 0;
}

///////////////////////////////////////////////////////////////////////////////
// APIs
///////////////////////////////////////////////////////////////////////////////
RSMetadataEncoder *CreateRSMetadataEncoder(llvm::Module *M) {
  return reinterpret_cast<RSMetadataEncoder*>(new RSMetadataEncoderInternal(M));
}

int RSEncodeVarMetadata(RSMetadataEncoder *E, const RSVar *V) {
  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSVar(V);
}

int RSEncodeFunctionMetadata(RSMetadataEncoder *E, const RSFunction *F) {
  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSFunc(F);
}

void DestroyRSMetadataEncoder(RSMetadataEncoder *E) {
  RSMetadataEncoderInternal *C =
      reinterpret_cast<RSMetadataEncoderInternal*>(E);
  delete C;
  return;
}

int FinalizeRSMetadataEncoder(RSMetadataEncoder *E) {
  RSMetadataEncoderInternal *C =
      reinterpret_cast<RSMetadataEncoderInternal*>(E);
  int Res = C->finalize();
  DestroyRSMetadataEncoder(E);
  return Res;
}
