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