blob: aa02c57b1c6ea64f6451cafb4a495175386a0e6e [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
Zonr Chang66a1a5a2010-10-22 11:00:11 +080030#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.
Stephen Hinese639eb52010-11-08 19:27:20 -080082 inline bool checkReturnIndex(unsigned *Index) {
83 if (*Index == 0)
Zonr Chang66a1a5a2010-10-22 11:00:11 +080084 return false;
85 else
Stephen Hinese639eb52010-11-08 19:27:20 -080086 (*Index)--;
Zonr Chang66a1a5a2010-10-22 11:00:11 +080087 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:
Stephen Hinese639eb52010-11-08 19:27:20 -0800105 explicit RSMetadataEncoderInternal(llvm::Module *M);
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800106
107 int encodeRSVar(const RSVar *V);
108 int encodeRSFunc(const RSFunction *F);
109
110 int finalize();
111};
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800112}
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));
Stephen Hinese639eb52010-11-08 19:27:20 -0800181 if (!checkReturnIndex(&PointeeType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800182 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));
Stephen Hinese639eb52010-11-08 19:27:20 -0800203 if (!checkReturnIndex(&ElementType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800204 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);
Stephen Hinese639eb52010-11-08 19:27:20 -0800227 if (!checkReturnIndex(&RecordName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800228 return 0;
229
230 unsigned Base = encodeTypeBase(RS_GET_TYPE_BASE(T));
Stephen Hinese639eb52010-11-08 19:27:20 -0800231 if (!checkReturnIndex(&Base))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800232 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));
Stephen Hinese639eb52010-11-08 19:27:20 -0800265 if (!checkReturnIndex(&FieldName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800266 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));
Stephen Hinese639eb52010-11-08 19:27:20 -0800274 if (!checkReturnIndex(&FieldType))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800275 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);
Stephen Hinese639eb52010-11-08 19:27:20 -0800314 if (!checkReturnIndex(&VarName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800315 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);
Stephen Hinese639eb52010-11-08 19:27:20 -0800344 if (!checkReturnIndex(&FuncName))
Zonr Chang66a1a5a2010-10-22 11:00:11 +0800345 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}