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 #include "rsDefines.h"
21
22 #define LOG_TAG "bcinfo"
23 #include <cutils/log.h>
24 #ifdef HAVE_ANDROID_OS
25 #include <cutils/properties.h>
26 #endif
27
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/IR/Function.h"
33 #include "llvm/Support/MemoryBuffer.h"
34
35 #include <cstdlib>
36
37 namespace bcinfo {
38
39 namespace {
40
getStringOperand(const llvm::Metadata * node)41 llvm::StringRef getStringOperand(const llvm::Metadata *node) {
42 if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
43 return mds->getString();
44 }
45 return llvm::StringRef();
46 }
47
extractUIntFromMetadataString(uint32_t * value,const llvm::Metadata * m)48 bool extractUIntFromMetadataString(uint32_t *value,
49 const llvm::Metadata *m) {
50 llvm::StringRef SigString = getStringOperand(m);
51 if (SigString != "") {
52 if (!SigString.getAsInteger(10, *value)) {
53 return true;
54 }
55 }
56 return false;
57 }
58
59 }
60
61 // Name of metadata node where pragma info resides (should be synced with
62 // slang.cpp)
63 static const llvm::StringRef PragmaMetadataName = "#pragma";
64
65 // Name of metadata node where exported variable names reside (should be
66 // synced with slang_rs_metadata.h)
67 static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
68
69 // Name of metadata node where exported function names reside (should be
70 // synced with slang_rs_metadata.h)
71 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
72
73 // Name of metadata node where exported ForEach name information resides
74 // (should be synced with slang_rs_metadata.h)
75 static const llvm::StringRef ExportForEachNameMetadataName =
76 "#rs_export_foreach_name";
77
78 // Name of metadata node where exported ForEach signature information resides
79 // (should be synced with slang_rs_metadata.h)
80 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
81
82 // Name of metadata node where RS object slot info resides (should be
83 // synced with slang_rs_metadata.h)
84 static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
85
86 static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
87
88 // Name of metadata node where the checksum for this build is stored. (should
89 // be synced with libbcc/lib/Core/Source.cpp)
90 static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
91
MetadataExtractor(const char * bitcode,size_t bitcodeSize)92 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
93 : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
94 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
95 mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
96 mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
97 mExportForEachInputCountList(nullptr), mPragmaCount(0),
98 mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
99 mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
100 mIsThreadable(true), mBuildChecksum(nullptr) {
101 BitcodeWrapper wrapper(bitcode, bitcodeSize);
102 mTargetAPI = wrapper.getTargetAPI();
103 mCompilerVersion = wrapper.getCompilerVersion();
104 mOptimizationLevel = wrapper.getOptimizationLevel();
105 }
106
107
MetadataExtractor(const llvm::Module * module)108 MetadataExtractor::MetadataExtractor(const llvm::Module *module)
109 : mModule(module), mBitcode(nullptr), mBitcodeSize(0), mExportVarCount(0),
110 mExportFuncCount(0), mExportForEachSignatureCount(0),
111 mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
112 mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
113 mExportForEachInputCountList(nullptr), mPragmaCount(0),
114 mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
115 mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
116 mIsThreadable(true), mBuildChecksum(nullptr) {
117 mCompilerVersion = RS_VERSION; // Default to the actual current version.
118 mOptimizationLevel = 3;
119 }
120
121
~MetadataExtractor()122 MetadataExtractor::~MetadataExtractor() {
123 if (mExportVarNameList) {
124 for (size_t i = 0; i < mExportVarCount; i++) {
125 delete [] mExportVarNameList[i];
126 mExportVarNameList[i] = nullptr;
127 }
128 }
129 delete [] mExportVarNameList;
130 mExportVarNameList = nullptr;
131
132 if (mExportFuncNameList) {
133 for (size_t i = 0; i < mExportFuncCount; i++) {
134 delete [] mExportFuncNameList[i];
135 mExportFuncNameList[i] = nullptr;
136 }
137 }
138 delete [] mExportFuncNameList;
139 mExportFuncNameList = nullptr;
140
141 if (mExportForEachNameList) {
142 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
143 delete [] mExportForEachNameList[i];
144 mExportForEachNameList[i] = nullptr;
145 }
146 }
147 delete [] mExportForEachNameList;
148 mExportForEachNameList = nullptr;
149
150 delete [] mExportForEachSignatureList;
151 mExportForEachSignatureList = nullptr;
152
153 for (size_t i = 0; i < mPragmaCount; i++) {
154 if (mPragmaKeyList) {
155 delete [] mPragmaKeyList[i];
156 mPragmaKeyList[i] = nullptr;
157 }
158 if (mPragmaValueList) {
159 delete [] mPragmaValueList[i];
160 mPragmaValueList[i] = nullptr;
161 }
162 }
163 delete [] mPragmaKeyList;
164 mPragmaKeyList = nullptr;
165 delete [] mPragmaValueList;
166 mPragmaValueList = nullptr;
167
168 delete [] mObjectSlotList;
169 mObjectSlotList = nullptr;
170
171 delete [] mBuildChecksum;
172
173 return;
174 }
175
176
populateObjectSlotMetadata(const llvm::NamedMDNode * ObjectSlotMetadata)177 bool MetadataExtractor::populateObjectSlotMetadata(
178 const llvm::NamedMDNode *ObjectSlotMetadata) {
179 if (!ObjectSlotMetadata) {
180 return true;
181 }
182
183 mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
184
185 if (!mObjectSlotCount) {
186 return true;
187 }
188
189 uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
190 memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
191
192 for (size_t i = 0; i < mObjectSlotCount; i++) {
193 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
194 if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
195 if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
196 ALOGE("Non-integer object slot value");
197 return false;
198 }
199 } else {
200 ALOGE("Corrupt object slot information");
201 return false;
202 }
203 }
204
205 mObjectSlotList = TmpSlotList;
206
207 return true;
208 }
209
210
createStringFromValue(llvm::Metadata * m)211 static const char *createStringFromValue(llvm::Metadata *m) {
212 auto ref = getStringOperand(m);
213 char *c = new char[ref.size() + 1];
214 memcpy(c, ref.data(), ref.size());
215 c[ref.size()] = '\0';
216 return c;
217 }
218
219
populatePragmaMetadata(const llvm::NamedMDNode * PragmaMetadata)220 void MetadataExtractor::populatePragmaMetadata(
221 const llvm::NamedMDNode *PragmaMetadata) {
222 if (!PragmaMetadata) {
223 return;
224 }
225
226 mPragmaCount = PragmaMetadata->getNumOperands();
227 if (!mPragmaCount) {
228 return;
229 }
230
231 const char **TmpKeyList = new const char*[mPragmaCount];
232 const char **TmpValueList = new const char*[mPragmaCount];
233
234 for (size_t i = 0; i < mPragmaCount; i++) {
235 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
236 if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
237 llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
238 TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
239 llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
240 TmpValueList[i] = createStringFromValue(PragmaValueMDS);
241 }
242 }
243
244 mPragmaKeyList = TmpKeyList;
245 mPragmaValueList = TmpValueList;
246
247 // Check to see if we have any FP precision-related pragmas.
248 std::string Relaxed("rs_fp_relaxed");
249 std::string Imprecise("rs_fp_imprecise");
250 std::string Full("rs_fp_full");
251 bool RelaxedPragmaSeen = false;
252 bool FullPragmaSeen = false;
253 for (size_t i = 0; i < mPragmaCount; i++) {
254 if (!Relaxed.compare(mPragmaKeyList[i])) {
255 RelaxedPragmaSeen = true;
256 } else if (!Imprecise.compare(mPragmaKeyList[i])) {
257 ALOGW("rs_fp_imprecise is deprecated. Assuming rs_fp_relaxed instead.");
258 RelaxedPragmaSeen = true;
259 } else if (!Full.compare(mPragmaKeyList[i])) {
260 FullPragmaSeen = true;
261 }
262 }
263
264 if (RelaxedPragmaSeen && FullPragmaSeen) {
265 ALOGE("Full and relaxed precision specified at the same time!");
266 }
267 mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
268
269 #ifdef HAVE_ANDROID_OS
270 // Provide an override for precsiion via adb shell setprop
271 // adb shell setprop debug.rs.precision rs_fp_full
272 // adb shell setprop debug.rs.precision rs_fp_relaxed
273 // adb shell setprop debug.rs.precision rs_fp_imprecise
274 char PrecisionPropBuf[PROPERTY_VALUE_MAX];
275 const std::string PrecisionPropName("debug.rs.precision");
276 property_get("debug.rs.precision", PrecisionPropBuf, "");
277 if (PrecisionPropBuf[0]) {
278 if (!Relaxed.compare(PrecisionPropBuf)) {
279 ALOGI("Switching to RS FP relaxed mode via setprop");
280 mRSFloatPrecision = RS_FP_Relaxed;
281 } else if (!Imprecise.compare(PrecisionPropBuf)) {
282 ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
283 "specified but is deprecated ");
284 mRSFloatPrecision = RS_FP_Relaxed;
285 } else if (!Full.compare(PrecisionPropBuf)) {
286 ALOGI("Switching to RS FP full mode via setprop");
287 mRSFloatPrecision = RS_FP_Full;
288 } else {
289 ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
290 }
291 }
292 #endif
293 }
294
295
populateVarNameMetadata(const llvm::NamedMDNode * VarNameMetadata)296 bool MetadataExtractor::populateVarNameMetadata(
297 const llvm::NamedMDNode *VarNameMetadata) {
298 if (!VarNameMetadata) {
299 return true;
300 }
301
302 mExportVarCount = VarNameMetadata->getNumOperands();
303 if (!mExportVarCount) {
304 return true;
305 }
306
307 const char **TmpNameList = new const char *[mExportVarCount];
308
309 for (size_t i = 0; i < mExportVarCount; i++) {
310 llvm::MDNode *Name = VarNameMetadata->getOperand(i);
311 if (Name != nullptr && Name->getNumOperands() > 1) {
312 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
313 }
314 }
315
316 mExportVarNameList = TmpNameList;
317
318 return true;
319 }
320
321
populateFuncNameMetadata(const llvm::NamedMDNode * FuncNameMetadata)322 bool MetadataExtractor::populateFuncNameMetadata(
323 const llvm::NamedMDNode *FuncNameMetadata) {
324 if (!FuncNameMetadata) {
325 return true;
326 }
327
328 mExportFuncCount = FuncNameMetadata->getNumOperands();
329 if (!mExportFuncCount) {
330 return true;
331 }
332
333 const char **TmpNameList = new const char*[mExportFuncCount];
334
335 for (size_t i = 0; i < mExportFuncCount; i++) {
336 llvm::MDNode *Name = FuncNameMetadata->getOperand(i);
337 if (Name != nullptr && Name->getNumOperands() == 1) {
338 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
339 }
340 }
341
342 mExportFuncNameList = TmpNameList;
343
344 return true;
345 }
346
347
calculateNumInputs(const llvm::Function * Function,uint32_t Signature)348 uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
349 uint32_t Signature) {
350
351 if (hasForEachSignatureIn(Signature)) {
352 uint32_t OtherCount = 0;
353
354 OtherCount += hasForEachSignatureUsrData(Signature);
355 OtherCount += hasForEachSignatureX(Signature);
356 OtherCount += hasForEachSignatureY(Signature);
357 OtherCount += hasForEachSignatureZ(Signature);
358 OtherCount += hasForEachSignatureCtxt(Signature);
359 OtherCount += hasForEachSignatureOut(Signature) &&
360 Function->getReturnType()->isVoidTy();
361
362 return Function->arg_size() - OtherCount;
363
364 } else {
365 return 0;
366 }
367 }
368
369
populateForEachMetadata(const llvm::NamedMDNode * Names,const llvm::NamedMDNode * Signatures)370 bool MetadataExtractor::populateForEachMetadata(
371 const llvm::NamedMDNode *Names,
372 const llvm::NamedMDNode *Signatures) {
373 if (!Names && !Signatures && mCompilerVersion == 0) {
374 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
375 // section for ForEach. We generate a full signature for a "root" function
376 // which means that we need to set the bottom 5 bits in the mask.
377 mExportForEachSignatureCount = 1;
378 char **TmpNameList = new char*[mExportForEachSignatureCount];
379 size_t RootLen = strlen(kRoot) + 1;
380 TmpNameList[0] = new char[RootLen];
381 strncpy(TmpNameList[0], kRoot, RootLen);
382
383 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
384 TmpSigList[0] = 0x1f;
385
386 mExportForEachNameList = (const char**)TmpNameList;
387 mExportForEachSignatureList = TmpSigList;
388 return true;
389 }
390
391 if (Signatures) {
392 mExportForEachSignatureCount = Signatures->getNumOperands();
393 if (!mExportForEachSignatureCount) {
394 return true;
395 }
396 } else {
397 mExportForEachSignatureCount = 0;
398 mExportForEachSignatureList = nullptr;
399 return true;
400 }
401
402 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
403 const char **TmpNameList = new const char*[mExportForEachSignatureCount];
404 uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];
405
406 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
407 llvm::MDNode *SigNode = Signatures->getOperand(i);
408 if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
409 if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
410 ALOGE("Non-integer signature value");
411 return false;
412 }
413 } else {
414 ALOGE("Corrupt signature information");
415 return false;
416 }
417 }
418
419 if (Names) {
420 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
421 llvm::MDNode *Name = Names->getOperand(i);
422 if (Name != nullptr && Name->getNumOperands() == 1) {
423 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
424
425 llvm::Function *Func =
426 mModule->getFunction(llvm::StringRef(TmpNameList[i]));
427
428 TmpInputCountList[i] = (Func != nullptr) ?
429 calculateNumInputs(Func, TmpSigList[i]) : 0;
430 }
431 }
432 } else {
433 if (mExportForEachSignatureCount != 1) {
434 ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
435 mExportForEachSignatureCount);
436 }
437 char *RootName = new char[5];
438 strncpy(RootName, "root", 5);
439 TmpNameList[0] = RootName;
440 }
441
442 mExportForEachNameList = TmpNameList;
443 mExportForEachSignatureList = TmpSigList;
444 mExportForEachInputCountList = TmpInputCountList;
445
446 return true;
447 }
448
449
readThreadableFlag(const llvm::NamedMDNode * ThreadableMetadata)450 void MetadataExtractor::readThreadableFlag(
451 const llvm::NamedMDNode *ThreadableMetadata) {
452
453 // Scripts are threadable by default. If we read a valid metadata value for
454 // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
455 // threadable. All other exception paths retain the default value.
456
457 mIsThreadable = true;
458 if (ThreadableMetadata == nullptr)
459 return;
460
461 llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
462 if (mdNode == nullptr)
463 return;
464
465 llvm::Metadata *mdValue = mdNode->getOperand(0);
466 if (mdValue == nullptr)
467 return;
468
469 if (getStringOperand(mdValue) == "no")
470 mIsThreadable = false;
471 }
472
readBuildChecksumMetadata(const llvm::NamedMDNode * ChecksumMetadata)473 void MetadataExtractor::readBuildChecksumMetadata(
474 const llvm::NamedMDNode *ChecksumMetadata) {
475
476 if (ChecksumMetadata == nullptr)
477 return;
478
479 llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
480 if (mdNode == nullptr)
481 return;
482
483 llvm::Metadata *mdValue = mdNode->getOperand(0);
484 if (mdValue == nullptr)
485 return;
486
487 mBuildChecksum = createStringFromValue(mdValue);
488 }
489
extract()490 bool MetadataExtractor::extract() {
491 if (!(mBitcode && mBitcodeSize) && !mModule) {
492 ALOGE("Invalid/empty bitcode/module");
493 return false;
494 }
495
496 std::unique_ptr<llvm::LLVMContext> mContext;
497
498 if (!mModule) {
499 mContext.reset(new llvm::LLVMContext());
500 std::unique_ptr<llvm::MemoryBuffer> MEM(
501 llvm::MemoryBuffer::getMemBuffer(
502 llvm::StringRef(mBitcode, mBitcodeSize), "", false));
503 std::string error;
504
505 // Module ownership is handled by the context, so we don't need to free it.
506 llvm::ErrorOr<llvm::Module* > errval = llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(),
507 *mContext);
508 if (std::error_code ec = errval.getError()) {
509 ALOGE("Could not parse bitcode file");
510 ALOGE("%s", ec.message().c_str());
511 return false;
512 }
513 mModule = errval.get();
514 }
515
516 const llvm::NamedMDNode *ExportVarMetadata =
517 mModule->getNamedMetadata(ExportVarMetadataName);
518 const llvm::NamedMDNode *ExportFuncMetadata =
519 mModule->getNamedMetadata(ExportFuncMetadataName);
520 const llvm::NamedMDNode *ExportForEachNameMetadata =
521 mModule->getNamedMetadata(ExportForEachNameMetadataName);
522 const llvm::NamedMDNode *ExportForEachMetadata =
523 mModule->getNamedMetadata(ExportForEachMetadataName);
524 const llvm::NamedMDNode *PragmaMetadata =
525 mModule->getNamedMetadata(PragmaMetadataName);
526 const llvm::NamedMDNode *ObjectSlotMetadata =
527 mModule->getNamedMetadata(ObjectSlotMetadataName);
528 const llvm::NamedMDNode *ThreadableMetadata =
529 mModule->getNamedMetadata(ThreadableMetadataName);
530 const llvm::NamedMDNode *ChecksumMetadata =
531 mModule->getNamedMetadata(ChecksumMetadataName);
532
533
534 if (!populateVarNameMetadata(ExportVarMetadata)) {
535 ALOGE("Could not populate export variable metadata");
536 return false;
537 }
538
539 if (!populateFuncNameMetadata(ExportFuncMetadata)) {
540 ALOGE("Could not populate export function metadata");
541 return false;
542 }
543
544 if (!populateForEachMetadata(ExportForEachNameMetadata,
545 ExportForEachMetadata)) {
546 ALOGE("Could not populate ForEach signature metadata");
547 return false;
548 }
549
550 populatePragmaMetadata(PragmaMetadata);
551
552 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
553 ALOGE("Could not populate object slot metadata");
554 return false;
555 }
556
557 readThreadableFlag(ThreadableMetadata);
558 readBuildChecksumMetadata(ChecksumMetadata);
559
560 return true;
561 }
562
563 } // namespace bcinfo
564