Home | History | Annotate | Download | only in bcinfo
      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 #include "rsDefines.h"
     21 
     22 #define LOG_TAG "bcinfo"
     23 #include <cutils/log.h>
     24 #ifdef HAVE_ANDROID_OS
     25 #include <cutils/properties.h>
     26 #endif
     27 
     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/IR/Function.h"
     33 #include "llvm/Support/MemoryBuffer.h"
     34 
     35 #include <cstdlib>
     36 
     37 namespace bcinfo {
     38 
     39 namespace {
     40 
     41 llvm::StringRef getStringOperand(const llvm::Metadata *node) {
     42   if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
     43     return mds->getString();
     44   }
     45   return llvm::StringRef();
     46 }
     47 
     48 bool extractUIntFromMetadataString(uint32_t *value,
     49     const llvm::Metadata *m) {
     50   llvm::StringRef SigString = getStringOperand(m);
     51   if (SigString != "") {
     52     if (!SigString.getAsInteger(10, *value)) {
     53       return true;
     54     }
     55   }
     56   return false;
     57 }
     58 
     59 }
     60 
     61 // Name of metadata node where pragma info resides (should be synced with
     62 // slang.cpp)
     63 static const llvm::StringRef PragmaMetadataName = "#pragma";
     64 
     65 // Name of metadata node where exported variable names reside (should be
     66 // synced with slang_rs_metadata.h)
     67 static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
     68 
     69 // Name of metadata node where exported function names reside (should be
     70 // synced with slang_rs_metadata.h)
     71 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
     72 
     73 // Name of metadata node where exported ForEach name information resides
     74 // (should be synced with slang_rs_metadata.h)
     75 static const llvm::StringRef ExportForEachNameMetadataName =
     76     "#rs_export_foreach_name";
     77 
     78 // Name of metadata node where exported ForEach signature information resides
     79 // (should be synced with slang_rs_metadata.h)
     80 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
     81 
     82 // Name of metadata node where RS object slot info resides (should be
     83 // synced with slang_rs_metadata.h)
     84 static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
     85 
     86 static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
     87 
     88 // Name of metadata node where the checksum for this build is stored.  (should
     89 // be synced with libbcc/lib/Core/Source.cpp)
     90 static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
     91 
     92 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
     93     : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
     94       mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
     95       mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
     96       mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
     97       mExportForEachInputCountList(nullptr), mPragmaCount(0),
     98       mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
     99       mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
    100       mIsThreadable(true), mBuildChecksum(nullptr) {
    101   BitcodeWrapper wrapper(bitcode, bitcodeSize);
    102   mTargetAPI = wrapper.getTargetAPI();
    103   mCompilerVersion = wrapper.getCompilerVersion();
    104   mOptimizationLevel = wrapper.getOptimizationLevel();
    105 }
    106 
    107 
    108 MetadataExtractor::MetadataExtractor(const llvm::Module *module)
    109     : mModule(module), mBitcode(nullptr), mBitcodeSize(0), mExportVarCount(0),
    110       mExportFuncCount(0), mExportForEachSignatureCount(0),
    111       mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
    112       mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
    113       mExportForEachInputCountList(nullptr), mPragmaCount(0),
    114       mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
    115       mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
    116       mIsThreadable(true), mBuildChecksum(nullptr) {
    117   mCompilerVersion = RS_VERSION;  // Default to the actual current version.
    118   mOptimizationLevel = 3;
    119 }
    120 
    121 
    122 MetadataExtractor::~MetadataExtractor() {
    123   if (mExportVarNameList) {
    124     for (size_t i = 0; i < mExportVarCount; i++) {
    125         delete [] mExportVarNameList[i];
    126         mExportVarNameList[i] = nullptr;
    127     }
    128   }
    129   delete [] mExportVarNameList;
    130   mExportVarNameList = nullptr;
    131 
    132   if (mExportFuncNameList) {
    133     for (size_t i = 0; i < mExportFuncCount; i++) {
    134         delete [] mExportFuncNameList[i];
    135         mExportFuncNameList[i] = nullptr;
    136     }
    137   }
    138   delete [] mExportFuncNameList;
    139   mExportFuncNameList = nullptr;
    140 
    141   if (mExportForEachNameList) {
    142     for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
    143         delete [] mExportForEachNameList[i];
    144         mExportForEachNameList[i] = nullptr;
    145     }
    146   }
    147   delete [] mExportForEachNameList;
    148   mExportForEachNameList = nullptr;
    149 
    150   delete [] mExportForEachSignatureList;
    151   mExportForEachSignatureList = nullptr;
    152 
    153   for (size_t i = 0; i < mPragmaCount; i++) {
    154     if (mPragmaKeyList) {
    155       delete [] mPragmaKeyList[i];
    156       mPragmaKeyList[i] = nullptr;
    157     }
    158     if (mPragmaValueList) {
    159       delete [] mPragmaValueList[i];
    160       mPragmaValueList[i] = nullptr;
    161     }
    162   }
    163   delete [] mPragmaKeyList;
    164   mPragmaKeyList = nullptr;
    165   delete [] mPragmaValueList;
    166   mPragmaValueList = nullptr;
    167 
    168   delete [] mObjectSlotList;
    169   mObjectSlotList = nullptr;
    170 
    171   delete [] mBuildChecksum;
    172 
    173   return;
    174 }
    175 
    176 
    177 bool MetadataExtractor::populateObjectSlotMetadata(
    178     const llvm::NamedMDNode *ObjectSlotMetadata) {
    179   if (!ObjectSlotMetadata) {
    180     return true;
    181   }
    182 
    183   mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
    184 
    185   if (!mObjectSlotCount) {
    186     return true;
    187   }
    188 
    189   uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
    190   memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
    191 
    192   for (size_t i = 0; i < mObjectSlotCount; i++) {
    193     llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
    194     if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
    195       if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
    196         ALOGE("Non-integer object slot value");
    197         return false;
    198       }
    199     } else {
    200       ALOGE("Corrupt object slot information");
    201       return false;
    202     }
    203   }
    204 
    205   mObjectSlotList = TmpSlotList;
    206 
    207   return true;
    208 }
    209 
    210 
    211 static const char *createStringFromValue(llvm::Metadata *m) {
    212   auto ref = getStringOperand(m);
    213   char *c = new char[ref.size() + 1];
    214   memcpy(c, ref.data(), ref.size());
    215   c[ref.size()] = '\0';
    216   return c;
    217 }
    218 
    219 
    220 void MetadataExtractor::populatePragmaMetadata(
    221     const llvm::NamedMDNode *PragmaMetadata) {
    222   if (!PragmaMetadata) {
    223     return;
    224   }
    225 
    226   mPragmaCount = PragmaMetadata->getNumOperands();
    227   if (!mPragmaCount) {
    228     return;
    229   }
    230 
    231   const char **TmpKeyList = new const char*[mPragmaCount];
    232   const char **TmpValueList = new const char*[mPragmaCount];
    233 
    234   for (size_t i = 0; i < mPragmaCount; i++) {
    235     llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
    236     if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
    237       llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
    238       TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
    239       llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
    240       TmpValueList[i] = createStringFromValue(PragmaValueMDS);
    241     }
    242   }
    243 
    244   mPragmaKeyList = TmpKeyList;
    245   mPragmaValueList = TmpValueList;
    246 
    247   // Check to see if we have any FP precision-related pragmas.
    248   std::string Relaxed("rs_fp_relaxed");
    249   std::string Imprecise("rs_fp_imprecise");
    250   std::string Full("rs_fp_full");
    251   bool RelaxedPragmaSeen = false;
    252   bool FullPragmaSeen = false;
    253   for (size_t i = 0; i < mPragmaCount; i++) {
    254     if (!Relaxed.compare(mPragmaKeyList[i])) {
    255       RelaxedPragmaSeen = true;
    256     } else if (!Imprecise.compare(mPragmaKeyList[i])) {
    257       ALOGW("rs_fp_imprecise is deprecated.  Assuming rs_fp_relaxed instead.");
    258       RelaxedPragmaSeen = true;
    259     } else if (!Full.compare(mPragmaKeyList[i])) {
    260       FullPragmaSeen = true;
    261     }
    262   }
    263 
    264   if (RelaxedPragmaSeen && FullPragmaSeen) {
    265     ALOGE("Full and relaxed precision specified at the same time!");
    266   }
    267   mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
    268 
    269 #ifdef HAVE_ANDROID_OS
    270   // Provide an override for precsiion via adb shell setprop
    271   // adb shell setprop debug.rs.precision rs_fp_full
    272   // adb shell setprop debug.rs.precision rs_fp_relaxed
    273   // adb shell setprop debug.rs.precision rs_fp_imprecise
    274   char PrecisionPropBuf[PROPERTY_VALUE_MAX];
    275   const std::string PrecisionPropName("debug.rs.precision");
    276   property_get("debug.rs.precision", PrecisionPropBuf, "");
    277   if (PrecisionPropBuf[0]) {
    278     if (!Relaxed.compare(PrecisionPropBuf)) {
    279       ALOGI("Switching to RS FP relaxed mode via setprop");
    280       mRSFloatPrecision = RS_FP_Relaxed;
    281     } else if (!Imprecise.compare(PrecisionPropBuf)) {
    282       ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
    283             "specified but is deprecated ");
    284       mRSFloatPrecision = RS_FP_Relaxed;
    285     } else if (!Full.compare(PrecisionPropBuf)) {
    286       ALOGI("Switching to RS FP full mode via setprop");
    287       mRSFloatPrecision = RS_FP_Full;
    288     } else {
    289       ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
    290     }
    291   }
    292 #endif
    293 }
    294 
    295 
    296 bool MetadataExtractor::populateVarNameMetadata(
    297     const llvm::NamedMDNode *VarNameMetadata) {
    298   if (!VarNameMetadata) {
    299     return true;
    300   }
    301 
    302   mExportVarCount = VarNameMetadata->getNumOperands();
    303   if (!mExportVarCount) {
    304     return true;
    305   }
    306 
    307   const char **TmpNameList = new const char *[mExportVarCount];
    308 
    309   for (size_t i = 0; i < mExportVarCount; i++) {
    310     llvm::MDNode *Name = VarNameMetadata->getOperand(i);
    311     if (Name != nullptr && Name->getNumOperands() > 1) {
    312       TmpNameList[i] = createStringFromValue(Name->getOperand(0));
    313     }
    314   }
    315 
    316   mExportVarNameList = TmpNameList;
    317 
    318   return true;
    319 }
    320 
    321 
    322 bool MetadataExtractor::populateFuncNameMetadata(
    323     const llvm::NamedMDNode *FuncNameMetadata) {
    324   if (!FuncNameMetadata) {
    325     return true;
    326   }
    327 
    328   mExportFuncCount = FuncNameMetadata->getNumOperands();
    329   if (!mExportFuncCount) {
    330     return true;
    331   }
    332 
    333   const char **TmpNameList = new const char*[mExportFuncCount];
    334 
    335   for (size_t i = 0; i < mExportFuncCount; i++) {
    336     llvm::MDNode *Name = FuncNameMetadata->getOperand(i);
    337     if (Name != nullptr && Name->getNumOperands() == 1) {
    338       TmpNameList[i] = createStringFromValue(Name->getOperand(0));
    339     }
    340   }
    341 
    342   mExportFuncNameList = TmpNameList;
    343 
    344   return true;
    345 }
    346 
    347 
    348 uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
    349                                                uint32_t Signature) {
    350 
    351   if (hasForEachSignatureIn(Signature)) {
    352     uint32_t OtherCount = 0;
    353 
    354     OtherCount += hasForEachSignatureUsrData(Signature);
    355     OtherCount += hasForEachSignatureX(Signature);
    356     OtherCount += hasForEachSignatureY(Signature);
    357     OtherCount += hasForEachSignatureZ(Signature);
    358     OtherCount += hasForEachSignatureCtxt(Signature);
    359     OtherCount += hasForEachSignatureOut(Signature) &&
    360                   Function->getReturnType()->isVoidTy();
    361 
    362     return Function->arg_size() - OtherCount;
    363 
    364   } else {
    365     return 0;
    366   }
    367 }
    368 
    369 
    370 bool MetadataExtractor::populateForEachMetadata(
    371     const llvm::NamedMDNode *Names,
    372     const llvm::NamedMDNode *Signatures) {
    373   if (!Names && !Signatures && mCompilerVersion == 0) {
    374     // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
    375     // section for ForEach. We generate a full signature for a "root" function
    376     // which means that we need to set the bottom 5 bits in the mask.
    377     mExportForEachSignatureCount = 1;
    378     char **TmpNameList = new char*[mExportForEachSignatureCount];
    379     size_t RootLen = strlen(kRoot) + 1;
    380     TmpNameList[0] = new char[RootLen];
    381     strncpy(TmpNameList[0], kRoot, RootLen);
    382 
    383     uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
    384     TmpSigList[0] = 0x1f;
    385 
    386     mExportForEachNameList = (const char**)TmpNameList;
    387     mExportForEachSignatureList = TmpSigList;
    388     return true;
    389   }
    390 
    391   if (Signatures) {
    392     mExportForEachSignatureCount = Signatures->getNumOperands();
    393     if (!mExportForEachSignatureCount) {
    394       return true;
    395     }
    396   } else {
    397     mExportForEachSignatureCount = 0;
    398     mExportForEachSignatureList = nullptr;
    399     return true;
    400   }
    401 
    402   uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
    403   const char **TmpNameList = new const char*[mExportForEachSignatureCount];
    404   uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];
    405 
    406   for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
    407     llvm::MDNode *SigNode = Signatures->getOperand(i);
    408     if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
    409       if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
    410         ALOGE("Non-integer signature value");
    411         return false;
    412       }
    413     } else {
    414       ALOGE("Corrupt signature information");
    415       return false;
    416     }
    417   }
    418 
    419   if (Names) {
    420     for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
    421       llvm::MDNode *Name = Names->getOperand(i);
    422       if (Name != nullptr && Name->getNumOperands() == 1) {
    423         TmpNameList[i] = createStringFromValue(Name->getOperand(0));
    424 
    425         llvm::Function *Func =
    426             mModule->getFunction(llvm::StringRef(TmpNameList[i]));
    427 
    428         TmpInputCountList[i] = (Func != nullptr) ?
    429           calculateNumInputs(Func, TmpSigList[i]) : 0;
    430       }
    431     }
    432   } else {
    433     if (mExportForEachSignatureCount != 1) {
    434       ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
    435             mExportForEachSignatureCount);
    436     }
    437     char *RootName = new char[5];
    438     strncpy(RootName, "root", 5);
    439     TmpNameList[0] = RootName;
    440   }
    441 
    442   mExportForEachNameList = TmpNameList;
    443   mExportForEachSignatureList = TmpSigList;
    444   mExportForEachInputCountList = TmpInputCountList;
    445 
    446   return true;
    447 }
    448 
    449 
    450 void MetadataExtractor::readThreadableFlag(
    451     const llvm::NamedMDNode *ThreadableMetadata) {
    452 
    453   // Scripts are threadable by default.  If we read a valid metadata value for
    454   // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
    455   // threadable.  All other exception paths retain the default value.
    456 
    457   mIsThreadable = true;
    458   if (ThreadableMetadata == nullptr)
    459     return;
    460 
    461   llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
    462   if (mdNode == nullptr)
    463     return;
    464 
    465   llvm::Metadata *mdValue = mdNode->getOperand(0);
    466   if (mdValue == nullptr)
    467     return;
    468 
    469   if (getStringOperand(mdValue) == "no")
    470     mIsThreadable = false;
    471 }
    472 
    473 void MetadataExtractor::readBuildChecksumMetadata(
    474     const llvm::NamedMDNode *ChecksumMetadata) {
    475 
    476   if (ChecksumMetadata == nullptr)
    477     return;
    478 
    479   llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
    480   if (mdNode == nullptr)
    481     return;
    482 
    483   llvm::Metadata *mdValue = mdNode->getOperand(0);
    484   if (mdValue == nullptr)
    485     return;
    486 
    487   mBuildChecksum = createStringFromValue(mdValue);
    488 }
    489 
    490 bool MetadataExtractor::extract() {
    491   if (!(mBitcode && mBitcodeSize) && !mModule) {
    492     ALOGE("Invalid/empty bitcode/module");
    493     return false;
    494   }
    495 
    496   std::unique_ptr<llvm::LLVMContext> mContext;
    497 
    498   if (!mModule) {
    499     mContext.reset(new llvm::LLVMContext());
    500     std::unique_ptr<llvm::MemoryBuffer> MEM(
    501       llvm::MemoryBuffer::getMemBuffer(
    502         llvm::StringRef(mBitcode, mBitcodeSize), "", false));
    503     std::string error;
    504 
    505     // Module ownership is handled by the context, so we don't need to free it.
    506     llvm::ErrorOr<llvm::Module* > errval = llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(),
    507                                                                   *mContext);
    508     if (std::error_code ec = errval.getError()) {
    509         ALOGE("Could not parse bitcode file");
    510         ALOGE("%s", ec.message().c_str());
    511         return false;
    512     }
    513     mModule = errval.get();
    514   }
    515 
    516   const llvm::NamedMDNode *ExportVarMetadata =
    517       mModule->getNamedMetadata(ExportVarMetadataName);
    518   const llvm::NamedMDNode *ExportFuncMetadata =
    519       mModule->getNamedMetadata(ExportFuncMetadataName);
    520   const llvm::NamedMDNode *ExportForEachNameMetadata =
    521       mModule->getNamedMetadata(ExportForEachNameMetadataName);
    522   const llvm::NamedMDNode *ExportForEachMetadata =
    523       mModule->getNamedMetadata(ExportForEachMetadataName);
    524   const llvm::NamedMDNode *PragmaMetadata =
    525       mModule->getNamedMetadata(PragmaMetadataName);
    526   const llvm::NamedMDNode *ObjectSlotMetadata =
    527       mModule->getNamedMetadata(ObjectSlotMetadataName);
    528   const llvm::NamedMDNode *ThreadableMetadata =
    529       mModule->getNamedMetadata(ThreadableMetadataName);
    530   const llvm::NamedMDNode *ChecksumMetadata =
    531       mModule->getNamedMetadata(ChecksumMetadataName);
    532 
    533 
    534   if (!populateVarNameMetadata(ExportVarMetadata)) {
    535     ALOGE("Could not populate export variable metadata");
    536     return false;
    537   }
    538 
    539   if (!populateFuncNameMetadata(ExportFuncMetadata)) {
    540     ALOGE("Could not populate export function metadata");
    541     return false;
    542   }
    543 
    544   if (!populateForEachMetadata(ExportForEachNameMetadata,
    545                                ExportForEachMetadata)) {
    546     ALOGE("Could not populate ForEach signature metadata");
    547     return false;
    548   }
    549 
    550   populatePragmaMetadata(PragmaMetadata);
    551 
    552   if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
    553     ALOGE("Could not populate object slot metadata");
    554     return false;
    555   }
    556 
    557   readThreadableFlag(ThreadableMetadata);
    558   readBuildChecksumMetadata(ChecksumMetadata);
    559 
    560   return true;
    561 }
    562 
    563 }  // namespace bcinfo
    564