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