blob: 75384c61cd163a44c2ec9df43214fa4a0fe0b83c [file] [log] [blame]
Zonr Chang66a1a5a2010-10-22 11:00:11 +08001/*
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
Zonr Chang66a1a5a2010-10-22 11:00:11 +080019#include <cstdlib>
Stephen Hinese639eb52010-11-08 19:27:20 -080020#include <list>
21#include <map>
22#include <string>
Zonr Chang66a1a5a2010-10-22 11:00:11 +080023
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringRef.h"
26
Stephen Hinese639eb52010-11-08 19:27:20 -080027#include "llvm/Metadata.h"
28#include "llvm/Module.h"
29
Stephen Hines6e6578a2011-02-07 18:05:48 -080030#include "slang_assert.h"
Zonr Chang66a1a5a2010-10-22 11:00:11 +080031#include "slang_rs_type_spec.h"
32
33#define RS_METADATA_STRTAB_MN "#rs_metadata_strtab"
34#define RS_TYPE_INFO_MN "#rs_type_info"
35#define RS_EXPORT_VAR_MN "#rs_export_var"
36#define RS_EXPORT_FUNC_MN "#rs_export_func"
37#define RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX "%"
38
39///////////////////////////////////////////////////////////////////////////////
40// Useful utility functions
41///////////////////////////////////////////////////////////////////////////////
42static bool EncodeInteger(llvm::LLVMContext &C,
43 unsigned I,
44 llvm::SmallVectorImpl<llvm::Value*> &Op) {
45 llvm::StringRef S(reinterpret_cast<const char*>(&I), sizeof(I));
46 llvm::MDString *MDS = llvm::MDString::get(C, S);
47
48 if (MDS == NULL)
49 return false;
50 Op.push_back(MDS);
51 return true;
52}
53
54///////////////////////////////////////////////////////////////////////////////
55// class RSMetadataEncoderInternal
56///////////////////////////////////////////////////////////////////////////////
57namespace {
58
59class RSMetadataEncoderInternal {
60 private:
61 llvm::Module *mModule;
62
63 typedef std::map</* key */unsigned, unsigned/* index */> TypesMapTy;
64 TypesMapTy mTypes;
65 std::list<unsigned> mEncodedRSTypeInfo; // simply a sequece of integers
66 unsigned mCurTypeIndex;
67
68 // A special type for lookup created record type. It uses record name as key.
69 typedef std::map</* name */std::string, unsigned/* index */> RecordTypesMapTy;
70 RecordTypesMapTy mRecordTypes;
71
72 typedef std::map<std::string, unsigned/* index */> StringsMapTy;
73 StringsMapTy mStrings;
74 std::list<const char*> mEncodedStrings;
75 unsigned mCurStringIndex;
76
77 llvm::NamedMDNode *mVarInfoMetadata;
78 llvm::NamedMDNode *mFuncInfoMetadata;
79
80 // This function check the return value of function:
81 // joinString, encodeTypeBase, encode*Type(), encodeRSType, encodeRSVar,
82 // and encodeRSFunc. Return false if the value of Index indicates failure.
Stephen Hinese639eb52010-11-08 19:27:20 -080083 inline bool checkReturnIndex(unsigned *Index) {
84 if (*Index == 0)
Zonr Chang66a1a5a2010-10-22 11:00:11 +080085 return false;
86 else
Stephen Hinese639eb52010-11-08 19:27:20 -080087 (*Index)--;
Zonr Chang66a1a5a2010-10-22 11:00:11 +080088 return true;
89 }
90
91 unsigned joinString(const std::string &S);
92
93 unsigned encodeTypeBase(const struct RSTypeBase *Base);
94 unsigned encodeTypeBaseAsKey(const struct RSTypeBase *Base);
95#define ENUM_RS_DATA_TYPE_CLASS(x) \
96 unsigned encode ## x ## Type(const union RSType *T);
97RS_DATA_TYPE_CLASS_ENUMS
98#undef ENUM_RS_DATA_TYPE_CLASS
99
100 unsigned encodeRSType(const union RSType *T);
101
102 int flushStringTable();
103 int flushTypeInfo();
104
105 public:
Stephen Hinese639eb52010-11-08 19:27:20 -0800106 explicit RSMetadataEncoderInternal(llvm::Module *M);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800107
108 int encodeRSVar(const RSVar *V);
109 int encodeRSFunc(const RSFunction *F);
110
111 int finalize();
112};
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800113}
114
115RSMetadataEncoderInternal::RSMetadataEncoderInternal(llvm::Module *M)
116 : mModule(M),
117 mCurTypeIndex(0),
118 mCurStringIndex(0),
119 mVarInfoMetadata(NULL),
120 mFuncInfoMetadata(NULL) {
121 mTypes.clear();
122 mEncodedRSTypeInfo.clear();
123 mRecordTypes.clear();
124 mStrings.clear();
125
126 return;
127}
128
129// Return (StringIndex + 1) when successfully join the string and 0 if there's
130// any error.
131unsigned RSMetadataEncoderInternal::joinString(const std::string &S) {
132 StringsMapTy::const_iterator I = mStrings.find(S);
133
134 if (I != mStrings.end())
135 return (I->second + 1);
136
137 // Add S into mStrings
138 std::pair<StringsMapTy::iterator, bool> Res =
139 mStrings.insert(std::make_pair(S, mCurStringIndex));
140 // Insertion failed
141 if (!Res.second)
142 return 0;
143
144 // Add S into mEncodedStrings
145 mEncodedStrings.push_back(Res.first->first.c_str());
146 mCurStringIndex++;
147
148 // Return (StringIndex + 1)
149 return (Res.first->second + 1);
150}
151
152unsigned
153RSMetadataEncoderInternal::encodeTypeBase(const struct RSTypeBase *Base) {
154 mEncodedRSTypeInfo.push_back(Base->bits);
155 return ++mCurTypeIndex;
156}
157
158unsigned RSMetadataEncoderInternal::encodeTypeBaseAsKey(
159 const struct RSTypeBase *Base) {
160 TypesMapTy::const_iterator I = mTypes.find(Base->bits);
161 if (I != mTypes.end())
162 return (I->second + 1);
163
164 // Add Base into mTypes
165 std::pair<TypesMapTy::iterator, bool> Res =
166 mTypes.insert(std::make_pair(Base->bits, mCurTypeIndex));
167 // Insertion failed
168 if (!Res.second)
169 return 0;
170
171 // Push to mEncodedRSTypeInfo. This will also update mCurTypeIndex.
172 return encodeTypeBase(Base);
173}
174
175unsigned RSMetadataEncoderInternal::encodePrimitiveType(const union RSType *T) {
176 return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
177}
178
179unsigned RSMetadataEncoderInternal::encodePointerType(const union RSType *T) {
180 // Encode pointee type first
181 unsigned PointeeType = encodeRSType(RS_POINTER_TYPE_GET_POINTEE_TYPE(T));
Stephen Hinese639eb52010-11-08 19:27:20 -0800182 if (!checkReturnIndex(&PointeeType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800183 return 0;
184
185 unsigned Res = encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
186 // Push PointeeType after the base type
187 mEncodedRSTypeInfo.push_back(PointeeType);
188 return Res;
189}
190
191unsigned RSMetadataEncoderInternal::encodeVectorType(const union RSType *T) {
192 return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
193}
194
195unsigned RSMetadataEncoderInternal::encodeMatrixType(const union RSType *T) {
196 return encodeTypeBaseAsKey(RS_GET_TYPE_BASE(T));
197}
198
199unsigned
200RSMetadataEncoderInternal::encodeConstantArrayType(const union RSType *T) {
201 // Encode element type
202 unsigned ElementType =
203 encodeRSType(RS_CONSTANT_ARRAY_TYPE_GET_ELEMENT_TYPE(T));
Stephen Hinese639eb52010-11-08 19:27:20 -0800204 if (!checkReturnIndex(&ElementType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800205 return 0;
206
207 unsigned Res = encodeTypeBase(RS_GET_TYPE_BASE(T));
208 // Push the ElementType after the type base
209 mEncodedRSTypeInfo.push_back(ElementType);
210 return Res;
211}
212
213unsigned RSMetadataEncoderInternal::encodeRecordType(const union RSType *T) {
214 // Construct record name
215 std::string RecordInfoMetadataName(RS_EXPORT_RECORD_TYPE_NAME_MN_PREFIX);
216 RecordInfoMetadataName.append(RS_RECORD_TYPE_GET_NAME(T));
217
218 // Try to find it in mRecordTypes
219 RecordTypesMapTy::const_iterator I =
220 mRecordTypes.find(RecordInfoMetadataName);
221
222 // This record type has been encoded before. Fast return its index here.
223 if (I != mRecordTypes.end())
224 return (I->second + 1);
225
226 // Encode this record type into mTypes. Encode record name string first.
227 unsigned RecordName = joinString(RecordInfoMetadataName);
Stephen Hinese639eb52010-11-08 19:27:20 -0800228 if (!checkReturnIndex(&RecordName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800229 return 0;
230
231 unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
Stephen Hinese639eb52010-11-08 19:27:20 -0800232 if (!checkReturnIndex(&Base))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800233 return 0;
234
235 // Push record name after encoding the type base
236 mEncodedRSTypeInfo.push_back(RecordName);
237
238 // Add this record type into the map
239 std::pair<StringsMapTy::iterator, bool> Res =
240 mRecordTypes.insert(std::make_pair(RecordInfoMetadataName, Base));
241 // Insertion failed
242 if (!Res.second)
243 return 0;
244
245 // Create a named MDNode for this record type. We cannot create this before
246 // encoding type base into Types and updating mRecordTypes. This is because
247 // we may have structure like:
248 //
249 // struct foo {
250 // ...
251 // struct foo *bar; // self type reference
252 // ...
253 // }
254 llvm::NamedMDNode *RecordInfoMetadata =
255 mModule->getOrInsertNamedMetadata(RecordInfoMetadataName);
256
Stephen Hines6e6578a2011-02-07 18:05:48 -0800257 slangAssert((RecordInfoMetadata->getNumOperands() == 0) &&
258 "Record created before!");
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800259
260 // Encode field info into this named MDNode
261 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
262
263 for (unsigned i = 0; i < RS_RECORD_TYPE_GET_NUM_FIELDS(T); i++) {
264 // 1. field name
265 unsigned FieldName = joinString(RS_RECORD_TYPE_GET_FIELD_NAME(T, i));
Stephen Hinese639eb52010-11-08 19:27:20 -0800266 if (!checkReturnIndex(&FieldName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800267 return 0;
268 if (!EncodeInteger(mModule->getContext(),
269 FieldName,
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700270 FieldInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800271 return 0;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700272 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800273
274 // 2. field type
275 unsigned FieldType = encodeRSType(RS_RECORD_TYPE_GET_FIELD_TYPE(T, i));
Stephen Hinese639eb52010-11-08 19:27:20 -0800276 if (!checkReturnIndex(&FieldType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800277 return 0;
278 if (!EncodeInteger(mModule->getContext(),
279 FieldType,
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700280 FieldInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800281 return 0;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700282 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800283
284 // 3. field data kind
285 if (!EncodeInteger(mModule->getContext(),
286 RS_RECORD_TYPE_GET_FIELD_DATA_KIND(T, i),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700287 FieldInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800288 return 0;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700289 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800290
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700291 llvm::ArrayRef<llvm::Value*> FieldInfoArray(FieldInfo);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800292 RecordInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700293 FieldInfoArray));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800294 FieldInfo.clear();
295 }
296
297 return (Res.first->second + 1);
298}
299
300unsigned RSMetadataEncoderInternal::encodeRSType(const union RSType *T) {
301 switch (static_cast<enum RSTypeClass>(RS_TYPE_GET_CLASS(T))) {
302#define ENUM_RS_DATA_TYPE_CLASS(x) \
303 case RS_TC_ ## x: return encode ## x ## Type(T);
304 RS_DATA_TYPE_CLASS_ENUMS
305#undef ENUM_RS_DATA_TYPE_CLASS
306 default: return 0;
307 }
308 return 0;
309}
310
311int RSMetadataEncoderInternal::encodeRSVar(const RSVar *V) {
312 // check parameter
313 if ((V == NULL) || (V->name == NULL) || (V->type == NULL))
314 return -1;
315
316 // 1. var name
317 unsigned VarName = joinString(V->name);
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700318 if (!checkReturnIndex(&VarName)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800319 return -2;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700320 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800321
322 // 2. type
323 unsigned Type = encodeRSType(V->type);
324
325 llvm::SmallVector<llvm::Value*, 1> VarInfo;
326
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700327 if (!EncodeInteger(mModule->getContext(), VarName, VarInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800328 return -3;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700329 }
330 if (!EncodeInteger(mModule->getContext(), Type, VarInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800331 return -4;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700332 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800333
334 if (mVarInfoMetadata == NULL)
335 mVarInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
336
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700337 llvm::ArrayRef<llvm::Value*> VarInfoArray(VarInfo);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800338 mVarInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700339 VarInfoArray));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800340
341 return 0;
342}
343
344int RSMetadataEncoderInternal::encodeRSFunc(const RSFunction *F) {
345 // check parameter
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700346 if ((F == NULL) || (F->name == NULL)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800347 return -1;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700348 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800349
350 // 1. var name
351 unsigned FuncName = joinString(F->name);
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700352 if (!checkReturnIndex(&FuncName)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800353 return -2;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700354 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800355
356 llvm::SmallVector<llvm::Value*, 1> FuncInfo;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700357 if (!EncodeInteger(mModule->getContext(), FuncName, FuncInfo)) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800358 return -3;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700359 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800360
361 if (mFuncInfoMetadata == NULL)
362 mFuncInfoMetadata = mModule->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
363
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700364 llvm::ArrayRef<llvm::Value*> FuncInfoArray(FuncInfo);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800365 mFuncInfoMetadata->addOperand(llvm::MDNode::get(mModule->getContext(),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700366 FuncInfoArray));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800367
368 return 0;
369}
370
371// Write string table and string index table
372int RSMetadataEncoderInternal::flushStringTable() {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800373 slangAssert((mCurStringIndex == mEncodedStrings.size()));
374 slangAssert((mCurStringIndex == mStrings.size()));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800375
376 if (mCurStringIndex == 0)
377 return 0;
378
379 // Prepare named MDNode for string table and string index table.
380 llvm::NamedMDNode *RSMetadataStrTab =
381 mModule->getOrInsertNamedMetadata(RS_METADATA_STRTAB_MN);
382 RSMetadataStrTab->dropAllReferences();
383
384 unsigned StrTabSize = 0;
385 unsigned *StrIdx = reinterpret_cast<unsigned*>(
386 ::malloc((mStrings.size() + 1) * sizeof(unsigned)));
387
388 if (StrIdx == NULL)
389 return -1;
390
391 unsigned StrIdxI = 0; // iterator for array StrIdx
392
393 // count StrTabSize and fill StrIdx by the way
394 for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
395 E = mEncodedStrings.end();
396 I != E;
397 I++) {
398 StrIdx[StrIdxI++] = StrTabSize;
399 StrTabSize += ::strlen(*I) + 1 /* for '\0' */;
400 }
401 StrIdx[StrIdxI] = StrTabSize;
402
403 // Allocate
404 char *StrTab = reinterpret_cast<char*>(::malloc(StrTabSize));
405 if (StrTab == NULL) {
406 free(StrIdx);
407 return -1;
408 }
409
410 llvm::StringRef StrTabData(StrTab, StrTabSize);
411 llvm::StringRef StrIdxData(reinterpret_cast<const char*>(StrIdx),
412 mStrings.size() * sizeof(unsigned));
413
414 // Copy
415 StrIdxI = 1;
416 for (std::list<const char*>::const_iterator I = mEncodedStrings.begin(),
417 E = mEncodedStrings.end();
418 I != E;
419 I++) {
420 // Get string length from StrIdx (O(1)) instead of call strlen again (O(n)).
421 unsigned CurStrLength = StrIdx[StrIdxI] - StrIdx[StrIdxI - 1];
422 ::memcpy(StrTab, *I, CurStrLength);
423 // Move forward the pointer
424 StrTab += CurStrLength;
425 StrIdxI++;
426 }
427
428 // Flush to metadata
429 llvm::Value *StrTabMDS =
430 llvm::MDString::get(mModule->getContext(), StrTabData);
431 llvm::Value *StrIdxMDS =
432 llvm::MDString::get(mModule->getContext(), StrIdxData);
433
434 if ((StrTabMDS == NULL) || (StrIdxMDS == NULL)) {
435 free(StrIdx);
436 free(StrTab);
437 return -1;
438 }
439
440 llvm::SmallVector<llvm::Value*, 2> StrTabVal;
441 StrTabVal.push_back(StrTabMDS);
442 StrTabVal.push_back(StrIdxMDS);
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700443 llvm::ArrayRef<llvm::Value*> StrTabValArray(StrTabVal);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800444 RSMetadataStrTab->addOperand(llvm::MDNode::get(mModule->getContext(),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700445 StrTabValArray));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800446
447 return 0;
448}
449
450// Write RS type stream
451int RSMetadataEncoderInternal::flushTypeInfo() {
452 unsigned TypeInfoCount = mEncodedRSTypeInfo.size();
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700453 if (TypeInfoCount <= 0) {
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800454 return 0;
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700455 }
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800456
457 llvm::NamedMDNode *RSTypeInfo =
458 mModule->getOrInsertNamedMetadata(RS_TYPE_INFO_MN);
459 RSTypeInfo->dropAllReferences();
460
461 unsigned *TypeInfos =
462 reinterpret_cast<unsigned*>(::malloc(TypeInfoCount * sizeof(unsigned)));
463 unsigned TypeInfosIdx = 0; // iterator for array TypeInfos
464
465 if (TypeInfos == NULL)
466 return -1;
467
468 for (std::list<unsigned>::const_iterator I = mEncodedRSTypeInfo.begin(),
469 E = mEncodedRSTypeInfo.end();
470 I != E;
471 I++)
472 TypeInfos[TypeInfosIdx++] = *I;
473
474 llvm::StringRef TypeInfoData(reinterpret_cast<const char*>(TypeInfos),
475 TypeInfoCount * sizeof(unsigned));
476 llvm::Value *TypeInfoMDS =
477 llvm::MDString::get(mModule->getContext(), TypeInfoData);
478 if (TypeInfoMDS == NULL) {
479 free(TypeInfos);
480 return -1;
481 }
482
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700483 llvm::SmallVector<llvm::Value*, 1> TypeInfo;
484 TypeInfo.push_back(TypeInfoMDS);
485
486 llvm::ArrayRef<llvm::Value*> TypeInfoArray(TypeInfo);
487
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800488 RSTypeInfo->addOperand(llvm::MDNode::get(mModule->getContext(),
Shih-wei Liao83f0c622011-06-21 05:34:53 -0700489 TypeInfoArray));
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800490 free(TypeInfos);
491
492 return 0;
493}
494
495int RSMetadataEncoderInternal::finalize() {
496 int Res = flushStringTable();
497 if (Res != 0)
498 return Res;
499
500 Res = flushTypeInfo();
501 if (Res != 0)
502 return Res;
503
504 return 0;
505}
506
507///////////////////////////////////////////////////////////////////////////////
508// APIs
509///////////////////////////////////////////////////////////////////////////////
510RSMetadataEncoder *CreateRSMetadataEncoder(llvm::Module *M) {
511 return reinterpret_cast<RSMetadataEncoder*>(new RSMetadataEncoderInternal(M));
512}
513
514int RSEncodeVarMetadata(RSMetadataEncoder *E, const RSVar *V) {
515 return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSVar(V);
516}
517
518int RSEncodeFunctionMetadata(RSMetadataEncoder *E, const RSFunction *F) {
519 return reinterpret_cast<RSMetadataEncoderInternal*>(E)->encodeRSFunc(F);
520}
521
522void DestroyRSMetadataEncoder(RSMetadataEncoder *E) {
523 RSMetadataEncoderInternal *C =
524 reinterpret_cast<RSMetadataEncoderInternal*>(E);
525 delete C;
526 return;
527}
528
529int FinalizeRSMetadataEncoder(RSMetadataEncoder *E) {
530 RSMetadataEncoderInternal *C =
531 reinterpret_cast<RSMetadataEncoderInternal*>(E);
532 int Res = C->finalize();
533 DestroyRSMetadataEncoder(E);
534 return Res;
535}