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};
113e67239de8d94975e7e2216ee6860ae2e6cb8b15aStephen Hines
114e67239de8d94975e7e2216ee6860ae2e6cb8b15aStephen Hines}  // namespace
11566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
11666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::RSMetadataEncoderInternal(llvm::Module *M)
11766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    : mModule(M),
11866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mCurTypeIndex(0),
11966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mCurStringIndex(0),
12066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mVarInfoMetadata(NULL),
12166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mFuncInfoMetadata(NULL) {
12266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mTypes.clear();
12366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.clear();
12466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mRecordTypes.clear();
12566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mStrings.clear();
12666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
12766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return;
12866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
12966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
13066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Return (StringIndex + 1) when successfully join the string and 0 if there's
13166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// any error.
13266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::joinString(const std::string &S) {
13366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StringsMapTy::const_iterator I = mStrings.find(S);
13466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
13566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mStrings.end())
13666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
13766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
13866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add S into mStrings
13966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<StringsMapTy::iterator, bool> Res =
14066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mStrings.insert(std::make_pair(S, mCurStringIndex));
14166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
14266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
14366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
14466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
14566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add S into mEncodedStrings
14666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedStrings.push_back(Res.first->first.c_str());
14766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mCurStringIndex++;
14866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
14966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Return (StringIndex + 1)
15066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return (Res.first->second + 1);
15166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
15266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
15366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned
15466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::encodeTypeBase(const struct RSTypeBase *Base) {
15566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(Base->bits);
15666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return ++mCurTypeIndex;
15766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
15866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
15966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeTypeBaseAsKey(
16066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    const struct RSTypeBase *Base) {
16166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  TypesMapTy::const_iterator I = mTypes.find(Base->bits);
16266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mTypes.end())
16366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
16466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
16566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add Base into mTypes
16666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<TypesMapTy::iterator, bool> Res =
16766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mTypes.insert(std::make_pair(Base->bits, mCurTypeIndex));
16866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
16966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
17066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
17166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
17266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push to mEncodedRSTypeInfo. This will also update mCurTypeIndex.
17366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBase(Base);
17466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
17566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
17666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodePrimitiveType(const union RSType *T) {
17766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
17866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
17966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
18066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodePointerType(const union RSType *T) {
18166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode pointee type first
18266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned PointeeType = encodeRSType(RS_POINTER_TYPE_GET_POINTEE_TYPE(T));
183e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&PointeeType))
18466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
18566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
18666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Res = encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
18766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push PointeeType after the base type
18866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(PointeeType);
18966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
19066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeVectorType(const union RSType *T) {
19366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
19466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
19666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeMatrixType(const union RSType *T) {
19766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
19866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
19966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
20066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned
20166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoderInternal::encodeConstantArrayType(const union RSType *T) {
20266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode element type
20366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned ElementType =
20466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      encodeRSType(RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(T));
205e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&ElementType))
20666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
20766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
20866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Res = encodeTypeBase(RS_GET_TYPE_BASE(T));
20966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push the ElementType after the type base
21066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(ElementType);
21166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
21266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
21366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
21466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeRecordType(const union RSType *T) {
21566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Construct record name
21666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::string RecordInfoMetadataName(RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX);
21766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RecordInfoMetadataName.append(RS_RECORD_TYPE_GET_NAME(T));
21866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
21966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Try to find it in mRecordTypes
22066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RecordTypesMapTy::const_iterator I =
22166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mRecordTypes.find(RecordInfoMetadataName);
22266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
22366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // This record type has been encoded before. Fast return its index here.
22466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (I != mRecordTypes.end())
22566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return (I->second + 1);
22666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
22766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode this record type into mTypes. Encode record name string first.
22866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned RecordName = joinString(RecordInfoMetadataName);
229e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&RecordName))
23066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
23166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
233e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (!checkReturnIndex(&Base))
23466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
23566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Push record name after encoding the type base
23766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mEncodedRSTypeInfo.push_back(RecordName);
23866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
23966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Add this record type into the map
24066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  std::pair<StringsMapTy::iterator, bool> Res =
24166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mRecordTypes.insert(std::make_pair(RecordInfoMetadataName, Base));
24266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Insertion failed
24366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (!Res.second)
24466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
24566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
24666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Create a named MDNode for this record type. We cannot create this before
24766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // encoding type base into Types and updating mRecordTypes. This is because
24866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // we may have structure like:
24966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //
25066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //            struct foo {
25166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              ...
25266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              struct foo *bar;  // self type reference
25366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //              ...
25466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  //            }
25566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RecordInfoMetadata =
25666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RecordInfoMetadataName);
25766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
2586e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((RecordInfoMetadata->getNumOperands() == 0) &&
2596e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines              "Record created before!");
26066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
26166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Encode field info into this named MDNode
26266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 3> FieldInfo;
26366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
26466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (unsigned i = 0; i < RS_RECORD_TYPE_GET_NUM_FIELDS(T); i++) {
26566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // 1. field name
26666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned FieldName = joinString(RS_RECORD_TYPE_GET_FIELD_NAME(T, i));
267e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (!checkReturnIndex(&FieldName))
26866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
26966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    if (!EncodeInteger(mModule->getContext(),
27066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                       FieldName,
27183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao                       FieldInfo)) {
27266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
27383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao    }
27466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
27566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // 2. field type
27666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned FieldType = encodeRSType(RS_RECORD_TYPE_GET_FIELD_TYPE(T, i));
277e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (!checkReturnIndex(&FieldType))
27866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
27966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    if (!EncodeInteger(mModule->getContext(),
28066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                       FieldType,
28183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao                       FieldInfo)) {
28266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      return 0;
28383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao    }
28466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
28566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    RecordInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
28618c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                     FieldInfo));
28766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    FieldInfo.clear();
28866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
28966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
29066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return (Res.first->second + 1);
29166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
29266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
29366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changunsigned RSMetadataEncoderInternal::encodeRSType(const union RSType *T) {
29466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  switch (static_cast<enum RSTypeClass>(RS_TYPE_GET_CLASS(T))) {
29566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#define ENUM_RS_DATA_TYPE_CLASS(x)  \
29666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    case RS_TC_ ## x: return encode ## x ## Type(T);
29766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    RS_DATA_TYPE_CLASS_ENUMS
29866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang#undef ENUM_RS_DATA_TYPE_CLASS
29966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    default: return 0;
30066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
30166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
30266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
30366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
30466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::encodeRSVar(const RSVar *V) {
30566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // check parameter
30666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if ((V == NULL) || (V->name == NULL) || (V->type == NULL))
30766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
30866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
30966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 1. var name
31066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned VarName = joinString(V->name);
31183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!checkReturnIndex(&VarName)) {
31266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -2;
31383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
31466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
31566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 2. type
31666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned Type = encodeRSType(V->type);
31766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
31866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 1> VarInfo;
31966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
32083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), VarName, VarInfo)) {
32166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -3;
32283f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
32383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), Type, VarInfo)) {
32466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -4;
32583f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
32666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
32766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mVarInfoMetadata == NULL)
32866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    mVarInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
32966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mVarInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
33118c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                 VarInfo));
33266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
33466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
33566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
33666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::encodeRSFunc(const RSFunction *F) {
33766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // check parameter
33883f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if ((F == NULL) || (F->name == NULL)) {
33966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
34083f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
34166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
34266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // 1. var name
34366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned FuncName = joinString(F->name);
34483f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!checkReturnIndex(&FuncName)) {
34566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -2;
34683f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
34766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
34866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 1> FuncInfo;
34983f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (!EncodeInteger(mModule->getContext(), FuncName, FuncInfo)) {
35066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -3;
35183f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
35266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
35366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mFuncInfoMetadata == NULL)
35466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    mFuncInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
35566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
35666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  mFuncInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
35718c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                  FuncInfo));
35866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
35966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
36066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
36166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
36266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Write string table and string index table
36366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::flushStringTable() {
3646e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((mCurStringIndex == mEncodedStrings.size()));
3656e6578a360497f78a181e63d7783422a9c9bfb15Stephen Hines  slangAssert((mCurStringIndex == mStrings.size()));
36666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
36766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (mCurStringIndex == 0)
36866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
36966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
37066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Prepare named MDNode for string table and string index table.
37166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RSMetadataStrTab =
37266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RS_METADATA_STRTAB_MN);
37366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataStrTab->dropAllReferences();
37466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
37566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned StrTabSize = 0;
37666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned *StrIdx = reinterpret_cast<unsigned*>(
37766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                        ::malloc((mStrings.size() + 1) * sizeof(unsigned)));
37866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
37966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (StrIdx == NULL)
38066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
38166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
38266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned StrIdxI = 0;  // iterator for array StrIdx
38366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
38466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // count StrTabSize and fill StrIdx by the way
38566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
38666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedStrings.end();
38766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
38866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++) {
38966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrIdx[StrIdxI++] = StrTabSize;
39066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrTabSize += ::strlen(*I) + 1 /* for '\0' */;
39166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
39266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrIdx[StrIdxI] = StrTabSize;
39366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
39466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Allocate
39566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  char *StrTab = reinterpret_cast<char*>(::malloc(StrTabSize));
39666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (StrTab == NULL) {
39766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrIdx);
39866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
39966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
40066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
40166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef StrTabData(StrTab, StrTabSize);
40266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef StrIdxData(reinterpret_cast<const char*>(StrIdx),
40366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                             mStrings.size() * sizeof(unsigned));
40466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
40566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Copy
40666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrIdxI = 1;
40766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
40866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedStrings.end();
40966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
41066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++) {
41166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // Get string length from StrIdx (O(1)) instead of call strlen again (O(n)).
41266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    unsigned CurStrLength = StrIdx[StrIdxI] - StrIdx[StrIdxI - 1];
41366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    ::memcpy(StrTab, *I, CurStrLength);
41466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    // Move forward the pointer
41566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrTab += CurStrLength;
41666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    StrIdxI++;
41766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
41866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
41966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  // Flush to metadata
42066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *StrTabMDS =
42166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), StrTabData);
42266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *StrIdxMDS =
42366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), StrIdxData);
42466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
42566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if ((StrTabMDS == NULL) || (StrIdxMDS == NULL)) {
42666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrIdx);
42766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(StrTab);
42866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
42966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
43066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
43166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::SmallVector<llvm::Value*, 2> StrTabVal;
43266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrTabVal.push_back(StrTabMDS);
43366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  StrTabVal.push_back(StrIdxMDS);
43466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataStrTab->addOperand(llvm::MDNode::get(mModule->getContext(),
43518c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                                 StrTabVal));
43666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
43766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
43866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
43966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
44066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// Write RS type stream
44166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::flushTypeInfo() {
44266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned TypeInfoCount = mEncodedRSTypeInfo.size();
44383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  if (TypeInfoCount <= 0) {
44466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return 0;
44583f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  }
44666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
44766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::NamedMDNode *RSTypeInfo =
44866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      mModule->getOrInsertNamedMetadata(RS_TYPE_INFO_MN);
44966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSTypeInfo->dropAllReferences();
45066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
45166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned *TypeInfos =
45266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<unsigned*>(::malloc(TypeInfoCount * sizeof(unsigned)));
45366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  unsigned TypeInfosIdx = 0;  // iterator for array TypeInfos
45466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
45566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (TypeInfos == NULL)
45666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
45766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
45866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  for (std::list<unsigned>::const_iterator I = mEncodedRSTypeInfo.begin(),
45966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang          E = mEncodedRSTypeInfo.end();
46066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I != E;
46166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang       I++)
46266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    TypeInfos[TypeInfosIdx++] = *I;
46366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
46466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::StringRef TypeInfoData(reinterpret_cast<const char*>(TypeInfos),
46566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang                               TypeInfoCount * sizeof(unsigned));
46666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  llvm::Value *TypeInfoMDS =
46766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      llvm::MDString::get(mModule->getContext(), TypeInfoData);
46866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (TypeInfoMDS == NULL) {
46966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    free(TypeInfos);
47066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return -1;
47166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  }
47266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
47383f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  llvm::SmallVector<llvm::Value*, 1> TypeInfo;
47483f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao  TypeInfo.push_back(TypeInfoMDS);
47583f0c6261efc8f397fc2509e3862bc6d0eb1e1c4Shih-wei Liao
47666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
47718c8829f2bd3cbe0d02471588c6643c0a8c6ca3cStephen Hines                                           TypeInfo));
47866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  free(TypeInfos);
47966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
48066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
48166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
48266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
48366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSMetadataEncoderInternal::finalize() {
48466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int Res = flushStringTable();
48566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (Res != 0)
48666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return Res;
48766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
48866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  Res = flushTypeInfo();
48966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  if (Res != 0)
49066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang    return Res;
49166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
49266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return 0;
49366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
49466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
49566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
49666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang// APIs
49766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang///////////////////////////////////////////////////////////////////////////////
49866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr ChangRSMetadataEncoder *CreateRSMetadataEncoder(llvm::Module *M) {
49966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoder*>(new RSMetadataEncoderInternal(M));
50066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
50166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
50266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSEncodeVarMetadata(RSMetadataEncoder *E, const RSVar *V) {
50366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSVar(V);
50466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
50566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
50666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint RSEncodeFunctionMetadata(RSMetadataEncoder *E, const RSFunction *F) {
50766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSFunc(F);
50866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
50966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
51066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changvoid DestroyRSMetadataEncoder(RSMetadataEncoder *E) {
51166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataEncoderInternal *C =
51266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<RSMetadataEncoderInternal*>(E);
51366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  delete C;
51466a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return;
51566a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
51666a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang
51766a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Changint FinalizeRSMetadataEncoder(RSMetadataEncoder *E) {
51866a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  RSMetadataEncoderInternal *C =
51966a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang      reinterpret_cast<RSMetadataEncoderInternal*>(E);
52066a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  int Res = C->finalize();
52166a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  DestroyRSMetadataEncoder(E);
52266a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang  return Res;
52366a1a5abf5f2f771d33d6b70a84a1efd7fb22f23Zonr Chang}
524