MetadataExtractor.cpp revision 98abb2d77b6519a43c98427141ba1ded42441b8a
1/* 2 * Copyright 2011-2012, 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 "bcinfo/MetadataExtractor.h" 18 19#include "bcinfo/BitcodeWrapper.h" 20 21#define LOG_TAG "bcinfo" 22#include <cutils/log.h> 23 24#include "llvm/ADT/OwningPtr.h" 25#include "llvm/Bitcode/ReaderWriter.h" 26#include "llvm/Constants.h" 27#include "llvm/LLVMContext.h" 28#include "llvm/Module.h" 29#include "llvm/Support/MemoryBuffer.h" 30 31#include <cstdlib> 32 33namespace bcinfo { 34 35// Name of metadata node where pragma info resides (should be synced with 36// slang.cpp) 37static const llvm::StringRef PragmaMetadataName = "#pragma"; 38 39// Name of metadata node where exported variable names reside (should be 40// synced with slang_rs_metadata.h) 41static const llvm::StringRef ExportVarMetadataName = "#rs_export_var"; 42 43// Name of metadata node where exported function names reside (should be 44// synced with slang_rs_metadata.h) 45static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func"; 46 47// Name of metadata node where exported ForEach name information resides 48// (should be synced with slang_rs_metadata.h) 49static const llvm::StringRef ExportForEachNameMetadataName = 50 "#rs_export_foreach_name"; 51 52// Name of metadata node where exported ForEach signature information resides 53// (should be synced with slang_rs_metadata.h) 54static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach"; 55 56// Name of metadata node where RS object slot info resides (should be 57// synced with slang_rs_metadata.h) 58static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots"; 59 60 61MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize) 62 : mModule(NULL), mBitcode(bitcode), mBitcodeSize(bitcodeSize), 63 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0), 64 mExportVarNameList(NULL), mExportFuncNameList(NULL), 65 mExportForEachNameList(NULL), mExportForEachSignatureList(NULL), 66 mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL), 67 mObjectSlotCount(0), mObjectSlotList(NULL), 68 mRSFloatPrecision(RS_FP_Full) { 69 BitcodeWrapper wrapper(bitcode, bitcodeSize); 70 mCompilerVersion = wrapper.getCompilerVersion(); 71 mOptimizationLevel = wrapper.getOptimizationLevel(); 72} 73 74 75MetadataExtractor::MetadataExtractor(const llvm::Module *module) 76 : mModule(module), mBitcode(NULL), mBitcodeSize(0), mExportVarCount(0), 77 mExportFuncCount(0), mExportForEachSignatureCount(0), 78 mExportVarNameList(NULL), mExportFuncNameList(NULL), 79 mExportForEachNameList(NULL), mExportForEachSignatureList(NULL), 80 mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL), 81 mObjectSlotCount(0), mObjectSlotList(NULL), 82 mRSFloatPrecision(RS_FP_Full) { 83 mCompilerVersion = 0; 84 mOptimizationLevel = 3; 85} 86 87 88MetadataExtractor::~MetadataExtractor() { 89 if (mExportVarNameList) { 90 for (size_t i = 0; i < mExportVarCount; i++) { 91 delete [] mExportVarNameList[i]; 92 mExportVarNameList[i] = NULL; 93 } 94 } 95 delete [] mExportVarNameList; 96 mExportVarNameList = NULL; 97 98 if (mExportFuncNameList) { 99 for (size_t i = 0; i < mExportFuncCount; i++) { 100 delete [] mExportFuncNameList[i]; 101 mExportFuncNameList[i] = NULL; 102 } 103 } 104 delete [] mExportFuncNameList; 105 mExportFuncNameList = NULL; 106 107 if (mExportForEachNameList) { 108 for (size_t i = 0; i < mExportForEachSignatureCount; i++) { 109 delete [] mExportForEachNameList[i]; 110 mExportForEachNameList[i] = NULL; 111 } 112 } 113 delete [] mExportForEachNameList; 114 mExportForEachNameList = NULL; 115 116 delete [] mExportForEachSignatureList; 117 mExportForEachSignatureList = NULL; 118 119 for (size_t i = 0; i < mPragmaCount; i++) { 120 if (mPragmaKeyList) { 121 delete [] mPragmaKeyList[i]; 122 mPragmaKeyList[i] = NULL; 123 } 124 if (mPragmaValueList) { 125 delete [] mPragmaValueList[i]; 126 mPragmaValueList[i] = NULL; 127 } 128 } 129 delete [] mPragmaKeyList; 130 mPragmaKeyList = NULL; 131 delete [] mPragmaValueList; 132 mPragmaValueList = NULL; 133 134 delete [] mObjectSlotList; 135 mObjectSlotList = NULL; 136 137 return; 138} 139 140 141bool MetadataExtractor::populateObjectSlotMetadata( 142 const llvm::NamedMDNode *ObjectSlotMetadata) { 143 if (!ObjectSlotMetadata) { 144 return true; 145 } 146 147 mObjectSlotCount = ObjectSlotMetadata->getNumOperands(); 148 149 if (!mObjectSlotCount) { 150 return true; 151 } 152 153 uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount]; 154 memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList)); 155 156 for (size_t i = 0; i < mObjectSlotCount; i++) { 157 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i); 158 if (ObjectSlot != NULL && ObjectSlot->getNumOperands() == 1) { 159 llvm::Value *SlotMDS = ObjectSlot->getOperand(0); 160 if (SlotMDS->getValueID() == llvm::Value::MDStringVal) { 161 llvm::StringRef Slot = 162 static_cast<llvm::MDString*>(SlotMDS)->getString(); 163 uint32_t USlot = 0; 164 if (Slot.getAsInteger(10, USlot)) { 165 ALOGE("Non-integer object slot value '%s'", Slot.str().c_str()); 166 return false; 167 } 168 TmpSlotList[i] = USlot; 169 } 170 } 171 } 172 173 mObjectSlotList = TmpSlotList; 174 175 return true; 176} 177 178 179static const char *createStringFromValue(llvm::Value *v) { 180 if (v->getValueID() != llvm::Value::MDStringVal) { 181 return NULL; 182 } 183 184 llvm::StringRef ref = static_cast<llvm::MDString*>(v)->getString(); 185 186 char *c = new char[ref.size() + 1]; 187 memcpy(c, ref.data(), ref.size()); 188 c[ref.size()] = '\0'; 189 190 return c; 191} 192 193 194void MetadataExtractor::populatePragmaMetadata( 195 const llvm::NamedMDNode *PragmaMetadata) { 196 if (!PragmaMetadata) { 197 return; 198 } 199 200 mPragmaCount = PragmaMetadata->getNumOperands(); 201 if (!mPragmaCount) { 202 return; 203 } 204 205 const char **TmpKeyList = new const char*[mPragmaCount]; 206 const char **TmpValueList = new const char*[mPragmaCount]; 207 208 for (size_t i = 0; i < mPragmaCount; i++) { 209 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i); 210 if (Pragma != NULL && Pragma->getNumOperands() == 2) { 211 llvm::Value *PragmaKeyMDS = Pragma->getOperand(0); 212 TmpKeyList[i] = createStringFromValue(PragmaKeyMDS); 213 llvm::Value *PragmaValueMDS = Pragma->getOperand(1); 214 TmpValueList[i] = createStringFromValue(PragmaValueMDS); 215 } 216 } 217 218 mPragmaKeyList = TmpKeyList; 219 mPragmaValueList = TmpValueList; 220 221 // Check to see if we have any FP precision-related pragmas. 222 std::string Relaxed("rs_fp_relaxed"); 223 std::string Imprecise("rs_fp_imprecise"); 224 bool RelaxedPragmaSeen = false; 225 bool ImprecisePragmaSeen = false; 226 227 for (size_t i = 0; i < mPragmaCount; i++) { 228 if (!Relaxed.compare(mPragmaKeyList[i])) { 229 if (RelaxedPragmaSeen || ImprecisePragmaSeen) { 230 ALOGE("Multiple float precision pragmas specified!"); 231 } 232 RelaxedPragmaSeen = true; 233 } else if (!Imprecise.compare(mPragmaKeyList[i])) { 234 if (RelaxedPragmaSeen || ImprecisePragmaSeen) { 235 ALOGE("Multiple float precision pragmas specified!"); 236 } 237 ImprecisePragmaSeen = true; 238 } 239 } 240 241 // Imprecise is selected over Relaxed precision. 242 // In the absence of both, we stick to the default Full precision. 243 if (ImprecisePragmaSeen) { 244 mRSFloatPrecision = RS_FP_Imprecise; 245 } else if (RelaxedPragmaSeen) { 246 mRSFloatPrecision = RS_FP_Relaxed; 247 } 248 249 return; 250} 251 252 253bool MetadataExtractor::populateVarNameMetadata( 254 const llvm::NamedMDNode *VarNameMetadata) { 255 if (!VarNameMetadata) { 256 return true; 257 } 258 259 mExportVarCount = VarNameMetadata->getNumOperands(); 260 if (!mExportVarCount) { 261 return true; 262 } 263 264 const char **TmpNameList = new const char *[mExportVarCount]; 265 266 for (size_t i = 0; i < mExportVarCount; i++) { 267 llvm::MDNode *Name = VarNameMetadata->getOperand(i); 268 if (Name != NULL && Name->getNumOperands() > 1) { 269 TmpNameList[i] = createStringFromValue(Name->getOperand(0)); 270 } 271 } 272 273 mExportVarNameList = TmpNameList; 274 275 return true; 276} 277 278 279bool MetadataExtractor::populateFuncNameMetadata( 280 const llvm::NamedMDNode *FuncNameMetadata) { 281 if (!FuncNameMetadata) { 282 return true; 283 } 284 285 mExportFuncCount = FuncNameMetadata->getNumOperands(); 286 if (!mExportFuncCount) { 287 return true; 288 } 289 290 const char **TmpNameList = new const char*[mExportFuncCount]; 291 292 for (size_t i = 0; i < mExportFuncCount; i++) { 293 llvm::MDNode *Name = FuncNameMetadata->getOperand(i); 294 if (Name != NULL && Name->getNumOperands() == 1) { 295 TmpNameList[i] = createStringFromValue(Name->getOperand(0)); 296 } 297 } 298 299 mExportFuncNameList = TmpNameList; 300 301 return true; 302} 303 304 305bool MetadataExtractor::populateForEachMetadata( 306 const llvm::NamedMDNode *Names, 307 const llvm::NamedMDNode *Signatures) { 308 if (!Names || !Signatures) { 309 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata 310 // section for ForEach. We generate a full signature for a "root" function 311 // which means that we need to set the bottom 5 bits in the mask. 312 mExportForEachSignatureCount = 1; 313 char **TmpNameList = new char*[mExportForEachSignatureCount]; 314 TmpNameList[0] = new char[5]; 315 strncpy(TmpNameList[0], "root", 5); 316 317 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount]; 318 TmpSigList[0] = 0x1f; 319 320 mExportForEachNameList = (const char**)TmpNameList; 321 mExportForEachSignatureList = TmpSigList; 322 return true; 323 } 324 325 mExportForEachSignatureCount = Signatures->getNumOperands(); 326 if (!mExportForEachSignatureCount) { 327 return true; 328 } 329 330 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount]; 331 const char **TmpNameList = new const char*[mExportForEachSignatureCount]; 332 333 for (size_t i = 0; i < mExportForEachSignatureCount; i++) { 334 llvm::MDNode *SigNode = Signatures->getOperand(i); 335 if (SigNode != NULL && SigNode->getNumOperands() == 1) { 336 llvm::Value *SigVal = SigNode->getOperand(0); 337 if (SigVal->getValueID() == llvm::Value::MDStringVal) { 338 llvm::StringRef SigString = 339 static_cast<llvm::MDString*>(SigVal)->getString(); 340 uint32_t Signature = 0; 341 if (SigString.getAsInteger(10, Signature)) { 342 ALOGE("Non-integer signature value '%s'", SigString.str().c_str()); 343 return false; 344 } 345 TmpSigList[i] = Signature; 346 } 347 } 348 } 349 350 for (size_t i = 0; i < mExportForEachSignatureCount; i++) { 351 llvm::MDNode *Name = Names->getOperand(i); 352 if (Name != NULL && Name->getNumOperands() == 1) { 353 TmpNameList[i] = createStringFromValue(Name->getOperand(0)); 354 } 355 } 356 357 mExportForEachNameList = TmpNameList; 358 mExportForEachSignatureList = TmpSigList; 359 360 return true; 361} 362 363 364bool MetadataExtractor::extract() { 365 if (!(mBitcode && mBitcodeSize) && !mModule) { 366 ALOGE("Invalid/empty bitcode/module"); 367 return false; 368 } 369 370 llvm::OwningPtr<llvm::LLVMContext> mContext; 371 372 if (!mModule) { 373 mContext.reset(new llvm::LLVMContext()); 374 llvm::OwningPtr<llvm::MemoryBuffer> MEM( 375 llvm::MemoryBuffer::getMemBuffer( 376 llvm::StringRef(mBitcode, mBitcodeSize))); 377 std::string error; 378 379 // Module ownership is handled by the context, so we don't need to free it. 380 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &error); 381 if (!mModule) { 382 ALOGE("Could not parse bitcode file"); 383 ALOGE("%s", error.c_str()); 384 return false; 385 } 386 } 387 388 const llvm::NamedMDNode *ExportVarMetadata = 389 mModule->getNamedMetadata(ExportVarMetadataName); 390 const llvm::NamedMDNode *ExportFuncMetadata = 391 mModule->getNamedMetadata(ExportFuncMetadataName); 392 const llvm::NamedMDNode *ExportForEachNameMetadata = 393 mModule->getNamedMetadata(ExportForEachNameMetadataName); 394 const llvm::NamedMDNode *ExportForEachMetadata = 395 mModule->getNamedMetadata(ExportForEachMetadataName); 396 const llvm::NamedMDNode *PragmaMetadata = 397 mModule->getNamedMetadata(PragmaMetadataName); 398 const llvm::NamedMDNode *ObjectSlotMetadata = 399 mModule->getNamedMetadata(ObjectSlotMetadataName); 400 401 402 if (!populateVarNameMetadata(ExportVarMetadata)) { 403 ALOGE("Could not populate export variable metadata"); 404 return false; 405 } 406 407 if (!populateFuncNameMetadata(ExportFuncMetadata)) { 408 ALOGE("Could not populate export function metadata"); 409 return false; 410 } 411 412 if (!populateForEachMetadata(ExportForEachNameMetadata, 413 ExportForEachMetadata)) { 414 ALOGE("Could not populate ForEach signature metadata"); 415 return false; 416 } 417 418 populatePragmaMetadata(PragmaMetadata); 419 420 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) { 421 ALOGE("Could not populate object slot metadata"); 422 return false; 423 } 424 425 return true; 426} 427 428} // namespace bcinfo 429 430