166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang/*
266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * Copyright 2010, The Android Open Source Project
366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang *
466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * you may not use this file except in compliance with the License.
666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * You may obtain a copy of the License at
766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang *
866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang *
1066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * Unless required by applicable law or agreed to in writing, software
1166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
1266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * See the License for the specific language governing permissions and
1466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang * limitations under the License.
1566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang */
1666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
1766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include "slang_rs_metadata_spec.h"
1866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <cstdlib>
2066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include <list>
21e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <map>
2266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include <string>
2366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
2466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include "llvm/ADT/SmallVector.h"
2566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include "llvm/ADT/StringRef.h"
2666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
27e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Metadata.h"
28e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Module.h"
29e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
306e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines#include "slang_assert.h"
3166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#include "slang_rs_type_spec.h"
3266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
3366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define RS_METADATA_STRTAB_MN   "#rs_metadata_strtab"
3466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define RS_TYPE_INFO_MN         "#rs_type_info"
3566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define RS_EXPORT_VAR_MN        "#rs_export_var"
3666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define RS_EXPORT_FUNC_MN       "#rs_export_func"
3766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX  "%"
3866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
3966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
4066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Useful utility functions
4166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
4266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changstatic bool EncodeInteger(llvm::LLVMContext &C,
4366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                          unsigned I,
4466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                          llvm::SmallVectorImpl<llvm::Value*> &Op) {
4566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef S(reinterpret_cast<const char*>(&I), sizeof(I));
4666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::MDString *MDS = llvm::MDString::get(C, S);
4766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
4866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (MDS == NULL)
4966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return false;
5066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  Op.push_back(MDS);
5166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return true;
5266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
5366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
5466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
5566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// class RSMetadataEncoderInternal
5666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
5766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changnamespace {
5866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
5966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changclass RSMetadataEncoderInternal {
6066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang private:
6166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Module *mModule;
6266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
6366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  typedef std::map</* key */unsigned, unsigned/* index */> TypesMapTy;
6466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  TypesMapTy mTypes;
6566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::list<unsigned> mEncodedRSTypeInfo;  // simply a sequece of integers
6666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned mCurTypeIndex;
6766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
6866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // A special type for lookup created record type. It uses record name as key.
6966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  typedef std::map</* name */std::string, unsigned/* index */> RecordTypesMapTy;
7066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RecordTypesMapTy mRecordTypes;
7166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
7266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  typedef std::map<std::string, unsigned/* index */> StringsMapTy;
7366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StringsMapTy mStrings;
7466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::list<const char*> mEncodedStrings;
7566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned mCurStringIndex;
7666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
7766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *mVarInfoMetadata;
7866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *mFuncInfoMetadata;
7966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
8066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // This function check the return value of function:
8166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //   joinString, encodeTypeBase, encode*Type(), encodeRSType, encodeRSVar,
8266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //   and encodeRSFunc. Return false if the value of Index indicates failure.
83e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  inline bool checkReturnIndex(unsigned *Index) {
84e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (*Index == 0)
8566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return false;
8666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    else
87e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      (*Index)--;
8866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return true;
8966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
9066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
9166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned joinString(const std::string &S);
9266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
9366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned encodeTypeBase(const struct RSTypeBase *Base);
9466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned encodeTypeBaseAsKey(const struct RSTypeBase *Base);
9566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define ENUM_RS_DATA_TYPE_CLASS(x)  \
9666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned encode ## x ## Type(const union RSType *T);
9766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRS_DATA_TYPE_CLASS_ENUMS
9866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#undef ENUM_RS_DATA_TYPE_CLASS
9966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
10066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned encodeRSType(const union RSType *T);
10166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
10266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int flushStringTable();
10366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int flushTypeInfo();
10466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
10566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang public:
106e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  explicit RSMetadataEncoderInternal(llvm::Module *M);
10766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
10866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int encodeRSVar(const RSVar *V);
10966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int encodeRSFunc(const RSFunction *F);
11066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
11166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int finalize();
11266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang};
11366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
11466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
11566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::RSMetadataEncoderInternal(llvm::Module *M)
11666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    : mModule(M),
11766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mCurTypeIndex(0),
11866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mCurStringIndex(0),
11966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mVarInfoMetadata(NULL),
12066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mFuncInfoMetadata(NULL) {
12166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mTypes.clear();
12266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.clear();
12366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mRecordTypes.clear();
12466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mStrings.clear();
12566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
12666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return;
12766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
12866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
12966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Return (StringIndex + 1) when successfully join the string and 0 if there's
13066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// any error.
13166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::joinString(const std::string &S) {
13266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StringsMapTy::const_iterator I = mStrings.find(S);
13366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
13466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mStrings.end())
13566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
13666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
13766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add S into mStrings
13866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<StringsMapTy::iterator, bool> Res =
13966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mStrings.insert(std::make_pair(S, mCurStringIndex));
14066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
14166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
14266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
14366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
14466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add S into mEncodedStrings
14566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedStrings.push_back(Res.first->first.c_str());
14666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mCurStringIndex++;
14766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
14866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Return (StringIndex + 1)
14966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return (Res.first->second + 1);
15066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
15166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
15266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned
15366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::encodeTypeBase(const struct RSTypeBase *Base) {
15466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(Base->bits);
15566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return ++mCurTypeIndex;
15666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
15766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
15866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeTypeBaseAsKey(
15966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    const struct RSTypeBase *Base) {
16066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  TypesMapTy::const_iterator I = mTypes.find(Base->bits);
16166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mTypes.end())
16266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
16366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
16466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add Base into mTypes
16566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<TypesMapTy::iterator, bool> Res =
16666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mTypes.insert(std::make_pair(Base->bits, mCurTypeIndex));
16766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
16866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
16966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
17066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
17166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push to mEncodedRSTypeInfo. This will also update mCurTypeIndex.
17266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBase(Base);
17366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
17466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
17566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodePrimitiveType(const union RSType *T) {
17666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
17766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
17866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
17966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodePointerType(const union RSType *T) {
18066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode pointee type first
18166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned PointeeType = encodeRSType(RS_POINTER_TYPE_GET_POINTEE_TYPE(T));
182e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&PointeeType))
18366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
18466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
18566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Res = encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
18666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push PointeeType after the base type
18766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(PointeeType);
18866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
18966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeVectorType(const union RSType *T) {
19266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
19366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeMatrixType(const union RSType *T) {
19666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
19766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned
20066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::encodeConstantArrayType(const union RSType *T) {
20166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode element type
20266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned ElementType =
20366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      encodeRSType(RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(T));
204e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&ElementType))
20566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
20666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
20766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Res = encodeTypeBase(RS_GET_TYPE_BASE(T));
20866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push the ElementType after the type base
20966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(ElementType);
21066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
21166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
21266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
21366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeRecordType(const union RSType *T) {
21466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Construct record name
21566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::string RecordInfoMetadataName(RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX);
21666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RecordInfoMetadataName.append(RS_RECORD_TYPE_GET_NAME(T));
21766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
21866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Try to find it in mRecordTypes
21966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RecordTypesMapTy::const_iterator I =
22066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mRecordTypes.find(RecordInfoMetadataName);
22166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
22266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // This record type has been encoded before. Fast return its index here.
22366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mRecordTypes.end())
22466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
22566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
22666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode this record type into mTypes. Encode record name string first.
22766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned RecordName = joinString(RecordInfoMetadataName);
228e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&RecordName))
22966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
23066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
232e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&Base))
23366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
23466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push record name after encoding the type base
23666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(RecordName);
23766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add this record type into the map
23966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<StringsMapTy::iterator, bool> Res =
24066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mRecordTypes.insert(std::make_pair(RecordInfoMetadataName, Base));
24166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
24266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
24366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
24466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
24566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Create a named MDNode for this record type. We cannot create this before
24666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // encoding type base into Types and updating mRecordTypes. This is because
24766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // we may have structure like:
24866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //
24966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //            struct foo {
25066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              ...
25166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              struct foo *bar;  // self type reference
25266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              ...
25366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //            }
25466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RecordInfoMetadata =
25566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RecordInfoMetadataName);
25666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
2576e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((RecordInfoMetadata->getNumOperands() == 0) &&
2586e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "Record created before!");
25966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
26066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode field info into this named MDNode
26166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 3> FieldInfo;
26266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
26366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (unsigned i = 0; i < RS_RECORD_TYPE_GET_NUM_FIELDS(T); i++) {
26466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // 1. field name
26566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned FieldName = joinString(RS_RECORD_TYPE_GET_FIELD_NAME(T, i));
266e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (!checkReturnIndex(&FieldName))
26766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
26866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    if (!EncodeInteger(mModule->getContext(),
26966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                       FieldName,
27083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao                       FieldInfo)) {
27166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
27283f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao    }
27366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
27466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // 2. field type
27566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned FieldType = encodeRSType(RS_RECORD_TYPE_GET_FIELD_TYPE(T, i));
276e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (!checkReturnIndex(&FieldType))
27766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
27866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    if (!EncodeInteger(mModule->getContext(),
27966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                       FieldType,
28083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao                       FieldInfo)) {
28166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
28283f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao    }
28366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
28466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // 3. field data kind
28566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    if (!EncodeInteger(mModule->getContext(),
28666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                       RS_RECORD_TYPE_GET_FIELD_DATA_KIND(T, i),
28783f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao                       FieldInfo)) {
28866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
28983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao    }
29066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
29166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    RecordInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
29218c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                     FieldInfo));
29366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    FieldInfo.clear();
29466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
29566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
29666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return (Res.first->second + 1);
29766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
29866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
29966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeRSType(const union RSType *T) {
30066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  switch (static_cast<enum RSTypeClass>(RS_TYPE_GET_CLASS(T))) {
30166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define ENUM_RS_DATA_TYPE_CLASS(x)  \
30266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    case RS_TC_ ## x: return encode ## x ## Type(T);
30366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    RS_DATA_TYPE_CLASS_ENUMS
30466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#undef ENUM_RS_DATA_TYPE_CLASS
30566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    default: return 0;
30666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
30766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
30866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
30966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
31066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::encodeRSVar(const RSVar *V) {
31166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // check parameter
31266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if ((V == NULL) || (V->name == NULL) || (V->type == NULL))
31366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
31466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
31566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 1. var name
31666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned VarName = joinString(V->name);
31783f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!checkReturnIndex(&VarName)) {
31866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -2;
31983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
32066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
32166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 2. type
32266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Type = encodeRSType(V->type);
32366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
32466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 1> VarInfo;
32566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
32683f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), VarName, VarInfo)) {
32766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -3;
32883f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
32983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), Type, VarInfo)) {
33066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -4;
33183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
33266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mVarInfoMetadata == NULL)
33466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    mVarInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
33566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mVarInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
33718c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                 VarInfo));
33866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
34066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
34166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
34266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::encodeRSFunc(const RSFunction *F) {
34366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // check parameter
34483f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if ((F == NULL) || (F->name == NULL)) {
34566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
34683f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
34766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
34866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 1. var name
34966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned FuncName = joinString(F->name);
35083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!checkReturnIndex(&FuncName)) {
35166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -2;
35283f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
35366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
35466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 1> FuncInfo;
35583f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), FuncName, FuncInfo)) {
35666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -3;
35783f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
35866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
35966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mFuncInfoMetadata == NULL)
36066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    mFuncInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
36166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
36266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mFuncInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
36318c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                  FuncInfo));
36466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
36566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
36666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
36766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
36866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Write string table and string index table
36966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::flushStringTable() {
3706e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((mCurStringIndex == mEncodedStrings.size()));
3716e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((mCurStringIndex == mStrings.size()));
37266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
37366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mCurStringIndex == 0)
37466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
37566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
37666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Prepare named MDNode for string table and string index table.
37766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RSMetadataStrTab =
37866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RS_METADATA_STRTAB_MN);
37966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataStrTab->dropAllReferences();
38066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
38166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned StrTabSize = 0;
38266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned *StrIdx = reinterpret_cast<unsigned*>(
38366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                        ::malloc((mStrings.size() + 1) * sizeof(unsigned)));
38466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
38566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (StrIdx == NULL)
38666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
38766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
38866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned StrIdxI = 0;  // iterator for array StrIdx
38966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
39066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // count StrTabSize and fill StrIdx by the way
39166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
39266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedStrings.end();
39366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
39466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++) {
39566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrIdx[StrIdxI++] = StrTabSize;
39666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrTabSize += ::strlen(*I) + 1 /* for '\0' */;
39766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
39866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrIdx[StrIdxI] = StrTabSize;
39966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
40066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Allocate
40166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  char *StrTab = reinterpret_cast<char*>(::malloc(StrTabSize));
40266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (StrTab == NULL) {
40366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrIdx);
40466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
40566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
40666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
40766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef StrTabData(StrTab, StrTabSize);
40866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef StrIdxData(reinterpret_cast<const char*>(StrIdx),
40966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                             mStrings.size() * sizeof(unsigned));
41066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
41166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Copy
41266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrIdxI = 1;
41366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
41466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedStrings.end();
41566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
41666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++) {
41766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // Get string length from StrIdx (O(1)) instead of call strlen again (O(n)).
41866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned CurStrLength = StrIdx[StrIdxI] - StrIdx[StrIdxI - 1];
41966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    ::memcpy(StrTab, *I, CurStrLength);
42066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // Move forward the pointer
42166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrTab += CurStrLength;
42266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrIdxI++;
42366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
42466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
42566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Flush to metadata
42666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *StrTabMDS =
42766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), StrTabData);
42866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *StrIdxMDS =
42966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), StrIdxData);
43066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
43166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if ((StrTabMDS == NULL) || (StrIdxMDS == NULL)) {
43266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrIdx);
43366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrTab);
43466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
43566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
43666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
43766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 2> StrTabVal;
43866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrTabVal.push_back(StrTabMDS);
43966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrTabVal.push_back(StrIdxMDS);
44066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataStrTab->addOperand(llvm::MDNode::get(mModule->getContext(),
44118c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                 StrTabVal));
44266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
44366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
44466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
44566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
44666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Write RS type stream
44766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::flushTypeInfo() {
44866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned TypeInfoCount = mEncodedRSTypeInfo.size();
44983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (TypeInfoCount <= 0) {
45066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
45183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
45266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
45366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RSTypeInfo =
45466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RS_TYPE_INFO_MN);
45566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSTypeInfo->dropAllReferences();
45666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
45766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned *TypeInfos =
45866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<unsigned*>(::malloc(TypeInfoCount * sizeof(unsigned)));
45966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned TypeInfosIdx = 0;  // iterator for array TypeInfos
46066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
46166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (TypeInfos == NULL)
46266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
46366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
46466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<unsigned>::const_iterator I = mEncodedRSTypeInfo.begin(),
46566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedRSTypeInfo.end();
46666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
46766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++)
46866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    TypeInfos[TypeInfosIdx++] = *I;
46966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
47066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef TypeInfoData(reinterpret_cast<const char*>(TypeInfos),
47166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                               TypeInfoCount * sizeof(unsigned));
47266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *TypeInfoMDS =
47366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), TypeInfoData);
47466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (TypeInfoMDS == NULL) {
47566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(TypeInfos);
47666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
47766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
47866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
47983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  llvm::SmallVector<llvm::Value*, 1> TypeInfo;
48083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  TypeInfo.push_back(TypeInfoMDS);
48183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao
48266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
48318c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                           TypeInfo));
48466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  free(TypeInfos);
48566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
48666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
48766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
48866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
48966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::finalize() {
49066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int Res = flushStringTable();
49166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (Res != 0)
49266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return Res;
49366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
49466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  Res = flushTypeInfo();
49566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (Res != 0)
49666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return Res;
49766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
49866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
49966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
50066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
50166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
50266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// APIs
50366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
50466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoder *CreateRSMetadataEncoder(llvm::Module *M) {
50566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoder*>(new RSMetadataEncoderInternal(M));
50666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
50766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
50866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSEncodeVarMetadata(RSMetadataEncoder *E, const RSVar *V) {
50966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSVar(V);
51066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
51166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
51266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSEncodeFunctionMetadata(RSMetadataEncoder *E, const RSFunction *F) {
51366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSFunc(F);
51466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
51566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
51666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changvoid DestroyRSMetadataEncoder(RSMetadataEncoder *E) {
51766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataEncoderInternal *C =
51866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<RSMetadataEncoderInternal*>(E);
51966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  delete C;
52066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return;
52166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
52266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
52366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint FinalizeRSMetadataEncoder(RSMetadataEncoder *E) {
52466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataEncoderInternal *C =
52566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<RSMetadataEncoderInternal*>(E);
52666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int Res = C->finalize();
52766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  DestroyRSMetadataEncoder(E);
52866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
52966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
530