/*
 * 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_assert.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);

  slangAssert((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));
    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));

  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));

  return 0;
}

// Write string table and string index table
int RSMetadataEncoderInternal::flushStringTable() {
  slangAssert((mCurStringIndex == mEncodedStrings.size()));
  slangAssert((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));

  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;
  }

  llvm::SmallVector<llvm::Value*, 1> TypeInfo;
  TypeInfo.push_back(TypeInfoMDS);

  RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
                                           TypeInfo));
  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;
}
