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