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