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