• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MetadataExtractor(const char * bitcode,size_t bitcodeSize)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 
MetadataExtractor(const llvm::Module * module)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 
~MetadataExtractor()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 
populateObjectSlotMetadata(const llvm::NamedMDNode * ObjectSlotMetadata)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 
createStringFromValue(llvm::Value * v)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 
populatePragmaMetadata(const llvm::NamedMDNode * PragmaMetadata)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 
populateVarNameMetadata(const llvm::NamedMDNode * VarNameMetadata)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 
populateFuncNameMetadata(const llvm::NamedMDNode * FuncNameMetadata)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 
populateForEachMetadata(const llvm::NamedMDNode * Names,const llvm::NamedMDNode * Signatures)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 
extract()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