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 
     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