slang_rs_metadata_spec_encoder.cpp revision e639eb5caa2c386b4a60659a4929e8a6141a2cbe
1/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_metadata_spec.h"
18
19#include <cstdlib>
20#include <list>
21#include <map>
22#include <string>
23
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringRef.h"
26
27#include "llvm/Metadata.h"
28#include "llvm/Module.h"
29
30#include "slang_rs_type_spec.h"
31
32#define RS_METADATA_STRTAB_MN   "#rs_metadata_strtab"
33#define RS_TYPE_INFO_MN         "#rs_type_info"
34#define RS_EXPORT_VAR_MN        "#rs_export_var"
35#define RS_EXPORT_FUNC_MN       "#rs_export_func"
36#define RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX  "%"
37
38///////////////////////////////////////////////////////////////////////////////
39// Useful utility functions
40///////////////////////////////////////////////////////////////////////////////
41static bool EncodeInteger(llvm::LLVMContext &C,
42                          unsigned I,
43                          llvm::SmallVectorImpl<llvm::Value*> &Op) {
44  llvm::StringRef S(reinterpret_cast<const char*>(&I), sizeof(I));
45  llvm::MDString *MDS = llvm::MDString::get(C, S);
46
47  if (MDS == NULL)
48    return false;
49  Op.push_back(MDS);
50  return true;
51}
52
53///////////////////////////////////////////////////////////////////////////////
54// class RSMetadataEncoderInternal
55///////////////////////////////////////////////////////////////////////////////
56namespace {
57
58class RSMetadataEncoderInternal {
59 private:
60  llvm::Module *mModule;
61
62  typedef std::map</* key */unsigned, unsigned/* index */> TypesMapTy;
63  TypesMapTy mTypes;
64  std::list<unsigned> mEncodedRSTypeInfo;  // simply a sequece of integers
65  unsigned mCurTypeIndex;
66
67  // A special type for lookup created record type. It uses record name as key.
68  typedef std::map</* name */std::string, unsigned/* index */> RecordTypesMapTy;
69  RecordTypesMapTy mRecordTypes;
70
71  typedef std::map<std::string, unsigned/* index */> StringsMapTy;
72  StringsMapTy mStrings;
73  std::list<const char*> mEncodedStrings;
74  unsigned mCurStringIndex;
75
76  llvm::NamedMDNode *mVarInfoMetadata;
77  llvm::NamedMDNode *mFuncInfoMetadata;
78
79  // This function check the return value of function:
80  //   joinString, encodeTypeBase, encode*Type(), encodeRSType, encodeRSVar,
81  //   and encodeRSFunc. Return false if the value of Index indicates failure.
82  inline bool checkReturnIndex(unsigned *Index) {
83    if (*Index == 0)
84      return false;
85    else
86      (*Index)--;
87    return true;
88  }
89
90  unsigned joinString(const std::string &S);
91
92  unsigned encodeTypeBase(const struct RSTypeBase *Base);
93  unsigned encodeTypeBaseAsKey(const struct RSTypeBase *Base);
94#define ENUM_RS_DATA_TYPE_CLASS(x)  \
95  unsigned encode ## x ## Type(const union RSType *T);
96RS_DATA_TYPE_CLASS_ENUMS
97#undef ENUM_RS_DATA_TYPE_CLASS
98
99  unsigned encodeRSType(const union RSType *T);
100
101  int flushStringTable();
102  int flushTypeInfo();
103
104 public:
105  explicit RSMetadataEncoderInternal(llvm::Module *M);
106
107  int encodeRSVar(const RSVar *V);
108  int encodeRSFunc(const RSFunction *F);
109
110  int finalize();
111};
112}
113
114RSMetadataEncoderInternal::RSMetadataEncoderInternal(llvm::Module *M)
115    : mModule(M),
116      mCurTypeIndex(0),
117      mCurStringIndex(0),
118      mVarInfoMetadata(NULL),
119      mFuncInfoMetadata(NULL) {
120  mTypes.clear();
121  mEncodedRSTypeInfo.clear();
122  mRecordTypes.clear();
123  mStrings.clear();
124
125  return;
126}
127
128// Return (StringIndex + 1) when successfully join the string and 0 if there's
129// any error.
130unsigned RSMetadataEncoderInternal::joinString(const std::string &S) {
131  StringsMapTy::const_iterator I = mStrings.find(S);
132
133  if (I != mStrings.end())
134    return (I->second + 1);
135
136  // Add S into mStrings
137  std::pair<StringsMapTy::iterator, bool> Res =
138      mStrings.insert(std::make_pair(S, mCurStringIndex));
139  // Insertion failed
140  if (!Res.second)
141    return 0;
142
143  // Add S into mEncodedStrings
144  mEncodedStrings.push_back(Res.first->first.c_str());
145  mCurStringIndex++;
146
147  // Return (StringIndex + 1)
148  return (Res.first->second + 1);
149}
150
151unsigned
152RSMetadataEncoderInternal::encodeTypeBase(const struct RSTypeBase *Base) {
153  mEncodedRSTypeInfo.push_back(Base->bits);
154  return ++mCurTypeIndex;
155}
156
157unsigned RSMetadataEncoderInternal::encodeTypeBaseAsKey(
158    const struct RSTypeBase *Base) {
159  TypesMapTy::const_iterator I = mTypes.find(Base->bits);
160  if (I != mTypes.end())
161    return (I->second + 1);
162
163  // Add Base into mTypes
164  std::pair<TypesMapTy::iterator, bool> Res =
165      mTypes.insert(std::make_pair(Base->bits, mCurTypeIndex));
166  // Insertion failed
167  if (!Res.second)
168    return 0;
169
170  // Push to mEncodedRSTypeInfo. This will also update mCurTypeIndex.
171  return encodeTypeBase(Base);
172}
173
174unsigned RSMetadataEncoderInternal::encodePrimitiveType(const union RSType *T) {
175  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
176}
177
178unsigned RSMetadataEncoderInternal::encodePointerType(const union RSType *T) {
179  // Encode pointee type first
180  unsigned PointeeType = encodeRSType(RS_POINTER_TYPE_GET_POINTEE_TYPE(T));
181  if (!checkReturnIndex(&PointeeType))
182    return 0;
183
184  unsigned Res = encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
185  // Push PointeeType after the base type
186  mEncodedRSTypeInfo.push_back(PointeeType);
187  return Res;
188}
189
190unsigned RSMetadataEncoderInternal::encodeVectorType(const union RSType *T) {
191  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
192}
193
194unsigned RSMetadataEncoderInternal::encodeMatrixType(const union RSType *T) {
195  return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
196}
197
198unsigned
199RSMetadataEncoderInternal::encodeConstantArrayType(const union RSType *T) {
200  // Encode element type
201  unsigned ElementType =
202      encodeRSType(RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(T));
203  if (!checkReturnIndex(&ElementType))
204    return 0;
205
206  unsigned Res = encodeTypeBase(RS_GET_TYPE_BASE(T));
207  // Push the ElementType after the type base
208  mEncodedRSTypeInfo.push_back(ElementType);
209  return Res;
210}
211
212unsigned RSMetadataEncoderInternal::encodeRecordType(const union RSType *T) {
213  // Construct record name
214  std::string RecordInfoMetadataName(RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX);
215  RecordInfoMetadataName.append(RS_RECORD_TYPE_GET_NAME(T));
216
217  // Try to find it in mRecordTypes
218  RecordTypesMapTy::const_iterator I =
219      mRecordTypes.find(RecordInfoMetadataName);
220
221  // This record type has been encoded before. Fast return its index here.
222  if (I != mRecordTypes.end())
223    return (I->second + 1);
224
225  // Encode this record type into mTypes. Encode record name string first.
226  unsigned RecordName = joinString(RecordInfoMetadataName);
227  if (!checkReturnIndex(&RecordName))
228    return 0;
229
230  unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
231  if (!checkReturnIndex(&Base))
232    return 0;
233
234  // Push record name after encoding the type base
235  mEncodedRSTypeInfo.push_back(RecordName);
236
237  // Add this record type into the map
238  std::pair<StringsMapTy::iterator, bool> Res =
239      mRecordTypes.insert(std::make_pair(RecordInfoMetadataName, Base));
240  // Insertion failed
241  if (!Res.second)
242    return 0;
243
244  // Create a named MDNode for this record type. We cannot create this before
245  // encoding type base into Types and updating mRecordTypes. This is because
246  // we may have structure like:
247  //
248  //            struct foo {
249  //              ...
250  //              struct foo *bar;  // self type reference
251  //              ...
252  //            }
253  llvm::NamedMDNode *RecordInfoMetadata =
254      mModule->getOrInsertNamedMetadata(RecordInfoMetadataName);
255
256  assert((RecordInfoMetadata->getNumOperands() == 0) &&
257         "Record created before!");
258
259  // Encode field info into this named MDNode
260  llvm::SmallVector<llvm::Value*, 3> FieldInfo;
261
262  for (unsigned i = 0; i < RS_RECORD_TYPE_GET_NUM_FIELDS(T); i++) {
263    // 1. field name
264    unsigned FieldName = joinString(RS_RECORD_TYPE_GET_FIELD_NAME(T, i));
265    if (!checkReturnIndex(&FieldName))
266      return 0;
267    if (!EncodeInteger(mModule->getContext(),
268                       FieldName,
269                       FieldInfo))
270      return 0;
271
272    // 2. field type
273    unsigned FieldType = encodeRSType(RS_RECORD_TYPE_GET_FIELD_TYPE(T, i));
274    if (!checkReturnIndex(&FieldType))
275      return 0;
276    if (!EncodeInteger(mModule->getContext(),
277                       FieldType,
278                       FieldInfo))
279      return 0;
280
281    // 3. field data kind
282    if (!EncodeInteger(mModule->getContext(),
283                       RS_RECORD_TYPE_GET_FIELD_DATA_KIND(T, i),
284                       FieldInfo))
285      return 0;
286
287    RecordInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
288                                                     FieldInfo.data(),
289                                                     FieldInfo.size()));
290    FieldInfo.clear();
291  }
292
293  return (Res.first->second + 1);
294}
295
296unsigned RSMetadataEncoderInternal::encodeRSType(const union RSType *T) {
297  switch (static_cast<enum RSTypeClass>(RS_TYPE_GET_CLASS(T))) {
298#define ENUM_RS_DATA_TYPE_CLASS(x)  \
299    case RS_TC_ ## x: return encode ## x ## Type(T);
300    RS_DATA_TYPE_CLASS_ENUMS
301#undef ENUM_RS_DATA_TYPE_CLASS
302    default: return 0;
303  }
304  return 0;
305}
306
307int RSMetadataEncoderInternal::encodeRSVar(const RSVar *V) {
308  // check parameter
309  if ((V == NULL) || (V->name == NULL) || (V->type == NULL))
310    return -1;
311
312  // 1. var name
313  unsigned VarName = joinString(V->name);
314  if (!checkReturnIndex(&VarName))
315    return -2;
316
317  // 2. type
318  unsigned Type = encodeRSType(V->type);
319
320  llvm::SmallVector<llvm::Value*, 1> VarInfo;
321
322  if (!EncodeInteger(mModule->getContext(), VarName, VarInfo))
323    return -3;
324  if (!EncodeInteger(mModule->getContext(), Type, VarInfo))
325    return -4;
326
327  if (mVarInfoMetadata == NULL)
328    mVarInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
329
330  mVarInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
331                                                 VarInfo.data(),
332                                                 VarInfo.size()));
333
334  return 0;
335}
336
337int RSMetadataEncoderInternal::encodeRSFunc(const RSFunction *F) {
338  // check parameter
339  if ((F == NULL) || (F->name == NULL))
340    return -1;
341
342  // 1. var name
343  unsigned FuncName = joinString(F->name);
344  if (!checkReturnIndex(&FuncName))
345    return -2;
346
347  llvm::SmallVector<llvm::Value*, 1> FuncInfo;
348  if (!EncodeInteger(mModule->getContext(), FuncName, FuncInfo))
349    return -3;
350
351  if (mFuncInfoMetadata == NULL)
352    mFuncInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
353
354  mFuncInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
355                                                  FuncInfo.data(),
356                                                  FuncInfo.size()));
357
358  return 0;
359}
360
361// Write string table and string index table
362int RSMetadataEncoderInternal::flushStringTable() {
363  assert((mCurStringIndex == mEncodedStrings.size()));
364  assert((mCurStringIndex == mStrings.size()));
365
366  if (mCurStringIndex == 0)
367    return 0;
368
369  // Prepare named MDNode for string table and string index table.
370  llvm::NamedMDNode *RSMetadataStrTab =
371      mModule->getOrInsertNamedMetadata(RS_METADATA_STRTAB_MN);
372  RSMetadataStrTab->dropAllReferences();
373
374  unsigned StrTabSize = 0;
375  unsigned *StrIdx = reinterpret_cast<unsigned*>(
376                        ::malloc((mStrings.size() + 1) * sizeof(unsigned)));
377
378  if (StrIdx == NULL)
379    return -1;
380
381  unsigned StrIdxI = 0;  // iterator for array StrIdx
382
383  // count StrTabSize and fill StrIdx by the way
384  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
385          E = mEncodedStrings.end();
386       I != E;
387       I++) {
388    StrIdx[StrIdxI++] = StrTabSize;
389    StrTabSize += ::strlen(*I) + 1 /* for '\0' */;
390  }
391  StrIdx[StrIdxI] = StrTabSize;
392
393  // Allocate
394  char *StrTab = reinterpret_cast<char*>(::malloc(StrTabSize));
395  if (StrTab == NULL) {
396    free(StrIdx);
397    return -1;
398  }
399
400  llvm::StringRef StrTabData(StrTab, StrTabSize);
401  llvm::StringRef StrIdxData(reinterpret_cast<const char*>(StrIdx),
402                             mStrings.size() * sizeof(unsigned));
403
404  // Copy
405  StrIdxI = 1;
406  for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
407          E = mEncodedStrings.end();
408       I != E;
409       I++) {
410    // Get string length from StrIdx (O(1)) instead of call strlen again (O(n)).
411    unsigned CurStrLength = StrIdx[StrIdxI] - StrIdx[StrIdxI - 1];
412    ::memcpy(StrTab, *I, CurStrLength);
413    // Move forward the pointer
414    StrTab += CurStrLength;
415    StrIdxI++;
416  }
417
418  // Flush to metadata
419  llvm::Value *StrTabMDS =
420      llvm::MDString::get(mModule->getContext(), StrTabData);
421  llvm::Value *StrIdxMDS =
422      llvm::MDString::get(mModule->getContext(), StrIdxData);
423
424  if ((StrTabMDS == NULL) || (StrIdxMDS == NULL)) {
425    free(StrIdx);
426    free(StrTab);
427    return -1;
428  }
429
430  llvm::SmallVector<llvm::Value*, 2> StrTabVal;
431  StrTabVal.push_back(StrTabMDS);
432  StrTabVal.push_back(StrIdxMDS);
433  RSMetadataStrTab->addOperand(llvm::MDNode::get(mModule->getContext(),
434                                                 StrTabVal.data(),
435                                                 StrTabVal.size()));
436
437  return 0;
438}
439
440// Write RS type stream
441int RSMetadataEncoderInternal::flushTypeInfo() {
442  unsigned TypeInfoCount = mEncodedRSTypeInfo.size();
443  if (TypeInfoCount <= 0)
444    return 0;
445
446  llvm::NamedMDNode *RSTypeInfo =
447      mModule->getOrInsertNamedMetadata(RS_TYPE_INFO_MN);
448  RSTypeInfo->dropAllReferences();
449
450  unsigned *TypeInfos =
451      reinterpret_cast<unsigned*>(::malloc(TypeInfoCount * sizeof(unsigned)));
452  unsigned TypeInfosIdx = 0;  // iterator for array TypeInfos
453
454  if (TypeInfos == NULL)
455    return -1;
456
457  for (std::list<unsigned>::const_iterator I = mEncodedRSTypeInfo.begin(),
458          E = mEncodedRSTypeInfo.end();
459       I != E;
460       I++)
461    TypeInfos[TypeInfosIdx++] = *I;
462
463  llvm::StringRef TypeInfoData(reinterpret_cast<const char*>(TypeInfos),
464                               TypeInfoCount * sizeof(unsigned));
465  llvm::Value *TypeInfoMDS =
466      llvm::MDString::get(mModule->getContext(), TypeInfoData);
467  if (TypeInfoMDS == NULL) {
468    free(TypeInfos);
469    return -1;
470  }
471
472  RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
473                                           &TypeInfoMDS, 1));
474  free(TypeInfos);
475
476  return 0;
477}
478
479int RSMetadataEncoderInternal::finalize() {
480  int Res = flushStringTable();
481  if (Res != 0)
482    return Res;
483
484  Res = flushTypeInfo();
485  if (Res != 0)
486    return Res;
487
488  return 0;
489}
490
491///////////////////////////////////////////////////////////////////////////////
492// APIs
493///////////////////////////////////////////////////////////////////////////////
494RSMetadataEncoder *CreateRSMetadataEncoder(llvm::Module *M) {
495  return reinterpret_cast<RSMetadataEncoder*>(new RSMetadataEncoderInternal(M));
496}
497
498int RSEncodeVarMetadata(RSMetadataEncoder *E, const RSVar *V) {
499  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSVar(V);
500}
501
502int RSEncodeFunctionMetadata(RSMetadataEncoder *E, const RSFunction *F) {
503  return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSFunc(F);
504}
505
506void DestroyRSMetadataEncoder(RSMetadataEncoder *E) {
507  RSMetadataEncoderInternal *C =
508      reinterpret_cast<RSMetadataEncoderInternal*>(E);
509  delete C;
510  return;
511}
512
513int FinalizeRSMetadataEncoder(RSMetadataEncoder *E) {
514  RSMetadataEncoderInternal *C =
515      reinterpret_cast<RSMetadataEncoderInternal*>(E);
516  int Res = C->finalize();
517  DestroyRSMetadataEncoder(E);
518  return Res;
519}
520