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 <log/log.h>
24
25 #include "Assert.h"
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/IR/Function.h"
32 #include "llvm/Support/MemoryBuffer.h"
33
34 #ifdef __ANDROID__
35 #include "Properties.h"
36 #endif
37
38 #include <cstdlib>
39
40 namespace bcinfo {
41
42 namespace {
43
getStringOperand(const llvm::Metadata * node)44 llvm::StringRef getStringOperand(const llvm::Metadata *node) {
45 if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
46 return mds->getString();
47 }
48 return llvm::StringRef();
49 }
50
extractUIntFromMetadataString(uint32_t * value,const llvm::Metadata * m)51 bool extractUIntFromMetadataString(uint32_t *value,
52 const llvm::Metadata *m) {
53 llvm::StringRef SigString = getStringOperand(m);
54 if (SigString != "") {
55 if (!SigString.getAsInteger(10, *value)) {
56 return true;
57 }
58 }
59 return false;
60 }
61
createStringFromValue(llvm::Metadata * m)62 const char *createStringFromValue(llvm::Metadata *m) {
63 auto ref = getStringOperand(m);
64 char *c = new char[ref.size() + 1];
65 memcpy(c, ref.data(), ref.size());
66 c[ref.size()] = '\0';
67 return c;
68 }
69
createStringFromOptionalValue(llvm::MDNode * n,unsigned opndNum)70 const char *createStringFromOptionalValue(llvm::MDNode *n, unsigned opndNum) {
71 llvm::Metadata *opnd;
72 if (opndNum >= n->getNumOperands() || !(opnd = n->getOperand(opndNum)))
73 return nullptr;
74 return createStringFromValue(opnd);
75 }
76
77 // Collect metadata from NamedMDNodes that contain a list of names
78 // (strings).
79 //
80 // Inputs:
81 //
82 // NamedMetadata - An LLVM metadata node, each of whose operands have
83 // a string as their first entry
84 //
85 // NameList - A reference that will hold an allocated array of strings
86 //
87 // Count - A reference that will hold the length of the allocated
88 // array of strings
89 //
90 // Return value:
91 //
92 // Return true on success, false on error.
93 //
94 // Upon success, the function sets NameList to an array of strings
95 // corresponding the names found in the metadata. The function sets
96 // Count to the number of entries in NameList.
97 //
98 // An error occurs if one of the metadata operands doesn't have a
99 // first entry.
populateNameMetadata(const llvm::NamedMDNode * NameMetadata,const char ** & NameList,size_t & Count)100 bool populateNameMetadata(const llvm::NamedMDNode *NameMetadata,
101 const char **&NameList, size_t &Count) {
102 if (!NameMetadata) {
103 NameList = nullptr;
104 Count = 0;
105 return true;
106 }
107
108 Count = NameMetadata->getNumOperands();
109 if (!Count) {
110 NameList = nullptr;
111 return true;
112 }
113
114 NameList = new const char *[Count];
115
116 for (size_t i = 0; i < Count; i++) {
117 llvm::MDNode *Name = NameMetadata->getOperand(i);
118 if (Name && Name->getNumOperands() > 0) {
119 NameList[i] = createStringFromValue(Name->getOperand(0));
120 } else {
121 ALOGE("Metadata operand does not contain a name string");
122 for (size_t AllocatedIndex = 0; AllocatedIndex < i; AllocatedIndex++) {
123 delete [] NameList[AllocatedIndex];
124 }
125 delete [] NameList;
126 NameList = nullptr;
127 Count = 0;
128
129 return false;
130 }
131 }
132
133 return true;
134 }
135
136 } // end anonymous namespace
137
138 // Name of metadata node where pragma info resides (should be synced with
139 // slang.cpp)
140 static const llvm::StringRef PragmaMetadataName = "#pragma";
141
142 // Name of metadata node where exported variable names reside (should be
143 // synced with slang_rs_metadata.h)
144 static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
145
146 // Name of metadata node where exported function names reside (should be
147 // synced with slang_rs_metadata.h)
148 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
149
150 // Name of metadata node where exported ForEach name information resides
151 // (should be synced with slang_rs_metadata.h)
152 static const llvm::StringRef ExportForEachNameMetadataName =
153 "#rs_export_foreach_name";
154
155 // Name of metadata node where exported ForEach signature information resides
156 // (should be synced with slang_rs_metadata.h)
157 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
158
159 // Name of metadata node where exported general reduce information resides
160 // (should be synced with slang_rs_metadata.h)
161 static const llvm::StringRef ExportReduceMetadataName = "#rs_export_reduce";
162
163 // Name of metadata node where RS object slot info resides (should be
164 // synced with slang_rs_metadata.h)
165 static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
166
167 static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
168
169 // Name of metadata node where the checksum for this build is stored. (should
170 // be synced with libbcc/lib/Core/Source.cpp)
171 static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
172
173 // Name of metadata node which contains a list of compile units that have debug
174 // metadata. If this is null then there is no debug metadata in the compile
175 // unit.
176 static const llvm::StringRef DebugInfoMetadataName = "llvm.dbg.cu";
177
178 const char MetadataExtractor::kWrapperMetadataName[] = "#rs_wrapper";
179
MetadataExtractor(const char * bitcode,size_t bitcodeSize)180 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
181 : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
182 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
183 mExportReduceCount(0), mExportVarNameList(nullptr),
184 mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
185 mExportForEachSignatureList(nullptr),
186 mExportForEachInputCountList(nullptr),
187 mExportReduceList(nullptr),
188 mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
189 mObjectSlotCount(0), mObjectSlotList(nullptr),
190 mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
191 mBuildChecksum(nullptr), mHasDebugInfo(false) {
192 BitcodeWrapper wrapper(bitcode, bitcodeSize);
193 mCompilerVersion = wrapper.getCompilerVersion();
194 mOptimizationLevel = wrapper.getOptimizationLevel();
195 }
196
MetadataExtractor(const llvm::Module * module)197 MetadataExtractor::MetadataExtractor(const llvm::Module *module)
198 : mModule(module), mBitcode(nullptr), mBitcodeSize(0),
199 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
200 mExportReduceCount(0), mExportVarNameList(nullptr),
201 mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
202 mExportForEachSignatureList(nullptr),
203 mExportForEachInputCountList(nullptr),
204 mExportReduceList(nullptr),
205 mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
206 mObjectSlotCount(0), mObjectSlotList(nullptr),
207 mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
208 mBuildChecksum(nullptr) {
209 const llvm::NamedMDNode *const wrapperMDNode = module->getNamedMetadata(kWrapperMetadataName);
210 bccAssert((wrapperMDNode != nullptr) && (wrapperMDNode->getNumOperands() == 1));
211 const llvm::MDNode *const wrapperMDTuple = wrapperMDNode->getOperand(0);
212
213 bool success = true;
214 success &= extractUIntFromMetadataString(&mCompilerVersion, wrapperMDTuple->getOperand(0));
215 success &= extractUIntFromMetadataString(&mOptimizationLevel, wrapperMDTuple->getOperand(1));
216 bccAssert(success);
217 }
218
219
~MetadataExtractor()220 MetadataExtractor::~MetadataExtractor() {
221 if (mExportVarNameList) {
222 for (size_t i = 0; i < mExportVarCount; i++) {
223 delete [] mExportVarNameList[i];
224 mExportVarNameList[i] = nullptr;
225 }
226 }
227 delete [] mExportVarNameList;
228 mExportVarNameList = nullptr;
229
230 if (mExportFuncNameList) {
231 for (size_t i = 0; i < mExportFuncCount; i++) {
232 delete [] mExportFuncNameList[i];
233 mExportFuncNameList[i] = nullptr;
234 }
235 }
236 delete [] mExportFuncNameList;
237 mExportFuncNameList = nullptr;
238
239 if (mExportForEachNameList) {
240 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
241 delete [] mExportForEachNameList[i];
242 mExportForEachNameList[i] = nullptr;
243 }
244 }
245 delete [] mExportForEachNameList;
246 mExportForEachNameList = nullptr;
247
248 delete [] mExportForEachSignatureList;
249 mExportForEachSignatureList = nullptr;
250
251 delete [] mExportForEachInputCountList;
252 mExportForEachInputCountList = nullptr;
253
254 delete [] mExportReduceList;
255 mExportReduceList = nullptr;
256
257 for (size_t i = 0; i < mPragmaCount; i++) {
258 if (mPragmaKeyList) {
259 delete [] mPragmaKeyList[i];
260 mPragmaKeyList[i] = nullptr;
261 }
262 if (mPragmaValueList) {
263 delete [] mPragmaValueList[i];
264 mPragmaValueList[i] = nullptr;
265 }
266 }
267 delete [] mPragmaKeyList;
268 mPragmaKeyList = nullptr;
269 delete [] mPragmaValueList;
270 mPragmaValueList = nullptr;
271
272 delete [] mObjectSlotList;
273 mObjectSlotList = nullptr;
274
275 delete [] mBuildChecksum;
276
277 return;
278 }
279
280
populateObjectSlotMetadata(const llvm::NamedMDNode * ObjectSlotMetadata)281 bool MetadataExtractor::populateObjectSlotMetadata(
282 const llvm::NamedMDNode *ObjectSlotMetadata) {
283 if (!ObjectSlotMetadata) {
284 return true;
285 }
286
287 mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
288
289 if (!mObjectSlotCount) {
290 return true;
291 }
292
293 uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
294 memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
295
296 for (size_t i = 0; i < mObjectSlotCount; i++) {
297 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
298 if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
299 if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
300 ALOGE("Non-integer object slot value");
301 return false;
302 }
303 } else {
304 ALOGE("Corrupt object slot information");
305 return false;
306 }
307 }
308
309 mObjectSlotList = TmpSlotList;
310
311 return true;
312 }
313
314
populatePragmaMetadata(const llvm::NamedMDNode * PragmaMetadata)315 void MetadataExtractor::populatePragmaMetadata(
316 const llvm::NamedMDNode *PragmaMetadata) {
317 if (!PragmaMetadata) {
318 return;
319 }
320
321 mPragmaCount = PragmaMetadata->getNumOperands();
322 if (!mPragmaCount) {
323 return;
324 }
325
326 const char **TmpKeyList = new const char*[mPragmaCount];
327 const char **TmpValueList = new const char*[mPragmaCount];
328
329 for (size_t i = 0; i < mPragmaCount; i++) {
330 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
331 if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
332 llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
333 TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
334 llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
335 TmpValueList[i] = createStringFromValue(PragmaValueMDS);
336 }
337 }
338
339 mPragmaKeyList = TmpKeyList;
340 mPragmaValueList = TmpValueList;
341
342 // Check to see if we have any FP precision-related pragmas.
343 std::string Relaxed("rs_fp_relaxed");
344 std::string Imprecise("rs_fp_imprecise");
345 std::string Full("rs_fp_full");
346 bool RelaxedPragmaSeen = false;
347 bool FullPragmaSeen = false;
348 for (size_t i = 0; i < mPragmaCount; i++) {
349 if (!Relaxed.compare(mPragmaKeyList[i])) {
350 RelaxedPragmaSeen = true;
351 } else if (!Imprecise.compare(mPragmaKeyList[i])) {
352 ALOGW("rs_fp_imprecise is deprecated. Assuming rs_fp_relaxed instead.");
353 RelaxedPragmaSeen = true;
354 } else if (!Full.compare(mPragmaKeyList[i])) {
355 FullPragmaSeen = true;
356 }
357 }
358
359 if (RelaxedPragmaSeen && FullPragmaSeen) {
360 ALOGE("Full and relaxed precision specified at the same time!");
361 }
362 mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
363
364 #ifdef __ANDROID__
365 // Provide an override for precsiion via adb shell setprop
366 // adb shell setprop debug.rs.precision rs_fp_full
367 // adb shell setprop debug.rs.precision rs_fp_relaxed
368 // adb shell setprop debug.rs.precision rs_fp_imprecise
369 char PrecisionPropBuf[PROP_VALUE_MAX];
370 const std::string PrecisionPropName("debug.rs.precision");
371 property_get("debug.rs.precision", PrecisionPropBuf, "");
372 if (PrecisionPropBuf[0]) {
373 if (!Relaxed.compare(PrecisionPropBuf)) {
374 ALOGI("Switching to RS FP relaxed mode via setprop");
375 mRSFloatPrecision = RS_FP_Relaxed;
376 } else if (!Imprecise.compare(PrecisionPropBuf)) {
377 ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
378 "specified but is deprecated ");
379 mRSFloatPrecision = RS_FP_Relaxed;
380 } else if (!Full.compare(PrecisionPropBuf)) {
381 ALOGI("Switching to RS FP full mode via setprop");
382 mRSFloatPrecision = RS_FP_Full;
383 } else {
384 ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
385 }
386 }
387 #endif
388 }
389
calculateNumInputs(const llvm::Function * Function,uint32_t Signature)390 uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
391 uint32_t Signature) {
392
393 if (hasForEachSignatureIn(Signature)) {
394 uint32_t OtherCount = 0;
395
396 OtherCount += hasForEachSignatureUsrData(Signature);
397 OtherCount += hasForEachSignatureX(Signature);
398 OtherCount += hasForEachSignatureY(Signature);
399 OtherCount += hasForEachSignatureZ(Signature);
400 OtherCount += hasForEachSignatureCtxt(Signature);
401 OtherCount += hasForEachSignatureOut(Signature) &&
402 Function->getReturnType()->isVoidTy();
403
404 return Function->arg_size() - OtherCount;
405
406 } else {
407 return 0;
408 }
409 }
410
411
populateForEachMetadata(const llvm::NamedMDNode * Names,const llvm::NamedMDNode * Signatures)412 bool MetadataExtractor::populateForEachMetadata(
413 const llvm::NamedMDNode *Names,
414 const llvm::NamedMDNode *Signatures) {
415 if (!Names && !Signatures && mCompilerVersion == 0) {
416 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
417 // section for ForEach. We generate a full signature for a "root" function
418 // which means that we need to set the bottom 5 bits in the mask.
419 mExportForEachSignatureCount = 1;
420 char **TmpNameList = new char*[mExportForEachSignatureCount];
421 size_t RootLen = strlen(kRoot) + 1;
422 TmpNameList[0] = new char[RootLen];
423 strncpy(TmpNameList[0], kRoot, RootLen);
424
425 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
426 TmpSigList[0] = 0x1f;
427
428 mExportForEachNameList = (const char**)TmpNameList;
429 mExportForEachSignatureList = TmpSigList;
430 return true;
431 }
432
433 if (Signatures) {
434 mExportForEachSignatureCount = Signatures->getNumOperands();
435 if (!mExportForEachSignatureCount) {
436 return true;
437 }
438 } else {
439 mExportForEachSignatureCount = 0;
440 mExportForEachSignatureList = nullptr;
441 return true;
442 }
443
444 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
445 const char **TmpNameList = new const char*[mExportForEachSignatureCount];
446 uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];
447
448 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
449 llvm::MDNode *SigNode = Signatures->getOperand(i);
450 if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
451 if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
452 ALOGE("Non-integer signature value");
453 return false;
454 }
455 } else {
456 ALOGE("Corrupt signature information");
457 return false;
458 }
459 }
460
461 if (Names) {
462 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
463 llvm::MDNode *Name = Names->getOperand(i);
464 if (Name != nullptr && Name->getNumOperands() == 1) {
465 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
466
467 // Note that looking up the function by name can fail: One of
468 // the uses of MetadataExtractor is as part of the
469 // RSEmbedInfoPass, which bcc_compat runs sufficiently late in
470 // the phase order that RSKernelExpandPass has already run and
471 // the original (UNexpanded) kernel function (TmpNameList[i])
472 // may have been deleted as having no references (if it has
473 // been inlined into the expanded kernel function and is
474 // otherwise unreferenced).
475 llvm::Function *Func =
476 mModule->getFunction(llvm::StringRef(TmpNameList[i]));
477
478 TmpInputCountList[i] = (Func != nullptr) ?
479 calculateNumInputs(Func, TmpSigList[i]) : 0;
480 }
481 }
482 } else {
483 if (mExportForEachSignatureCount != 1) {
484 ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
485 mExportForEachSignatureCount);
486 }
487 char *RootName = new char[5];
488 strncpy(RootName, "root", 5);
489 TmpNameList[0] = RootName;
490 }
491
492 mExportForEachNameList = TmpNameList;
493 mExportForEachSignatureList = TmpSigList;
494 mExportForEachInputCountList = TmpInputCountList;
495
496 return true;
497 }
498
499
populateReduceMetadata(const llvm::NamedMDNode * ReduceMetadata)500 bool MetadataExtractor::populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata) {
501 mExportReduceCount = 0;
502 mExportReduceList = nullptr;
503
504 if (!ReduceMetadata || !(mExportReduceCount = ReduceMetadata->getNumOperands()))
505 return true;
506
507 std::unique_ptr<Reduce[]> TmpReduceList(new Reduce[mExportReduceCount]);
508
509 for (size_t i = 0; i < mExportReduceCount; i++) {
510 llvm::MDNode *Node = ReduceMetadata->getOperand(i);
511 if (!Node || Node->getNumOperands() < 3) {
512 ALOGE("Missing reduce metadata");
513 return false;
514 }
515
516 TmpReduceList[i].mReduceName = createStringFromValue(Node->getOperand(0));
517
518 if (!extractUIntFromMetadataString(&TmpReduceList[i].mAccumulatorDataSize,
519 Node->getOperand(1))) {
520 ALOGE("Non-integer accumulator data size value in reduce metadata");
521 return false;
522 }
523
524 llvm::MDNode *AccumulatorNode = llvm::dyn_cast<llvm::MDNode>(Node->getOperand(2));
525 if (!AccumulatorNode || AccumulatorNode->getNumOperands() != 2) {
526 ALOGE("Malformed accumulator node in reduce metadata");
527 return false;
528 }
529 TmpReduceList[i].mAccumulatorName = createStringFromValue(AccumulatorNode->getOperand(0));
530 if (!extractUIntFromMetadataString(&TmpReduceList[i].mSignature,
531 AccumulatorNode->getOperand(1))) {
532 ALOGE("Non-integer signature value in reduce metadata");
533 return false;
534 }
535 // Note that looking up the function by name can fail: One of the
536 // uses of MetadataExtractor is as part of the RSEmbedInfoPass,
537 // which bcc_compat runs sufficiently late in the phase order that
538 // RSKernelExpandPass has already run and the original
539 // (UNexpanded) accumulator function (mAccumulatorName) may have
540 // been deleted as having no references (if it has been inlined
541 // into the expanded accumulator function and is otherwise
542 // unreferenced).
543 llvm::Function *Func =
544 mModule->getFunction(llvm::StringRef(TmpReduceList[i].mAccumulatorName));
545 // Why calculateNumInputs() - 1? The "-1" is because we don't
546 // want to treat the accumulator argument as an input.
547 TmpReduceList[i].mInputCount = (Func ? calculateNumInputs(Func, TmpReduceList[i].mSignature) - 1 : 0);
548
549 TmpReduceList[i].mInitializerName = createStringFromOptionalValue(Node, 3);
550 TmpReduceList[i].mCombinerName = createStringFromOptionalValue(Node, 4);
551 TmpReduceList[i].mOutConverterName = createStringFromOptionalValue(Node, 5);
552 TmpReduceList[i].mHalterName = createStringFromOptionalValue(Node, 6);
553 }
554
555 mExportReduceList = TmpReduceList.release();
556 return true;
557 }
558
readThreadableFlag(const llvm::NamedMDNode * ThreadableMetadata)559 void MetadataExtractor::readThreadableFlag(
560 const llvm::NamedMDNode *ThreadableMetadata) {
561
562 // Scripts are threadable by default. If we read a valid metadata value for
563 // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
564 // threadable. All other exception paths retain the default value.
565
566 mIsThreadable = true;
567 if (ThreadableMetadata == nullptr)
568 return;
569
570 llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
571 if (mdNode == nullptr)
572 return;
573
574 llvm::Metadata *mdValue = mdNode->getOperand(0);
575 if (mdValue == nullptr)
576 return;
577
578 if (getStringOperand(mdValue) == "no")
579 mIsThreadable = false;
580 }
581
readBuildChecksumMetadata(const llvm::NamedMDNode * ChecksumMetadata)582 void MetadataExtractor::readBuildChecksumMetadata(
583 const llvm::NamedMDNode *ChecksumMetadata) {
584
585 if (ChecksumMetadata == nullptr)
586 return;
587
588 llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
589 if (mdNode == nullptr)
590 return;
591
592 llvm::Metadata *mdValue = mdNode->getOperand(0);
593 if (mdValue == nullptr)
594 return;
595
596 mBuildChecksum = createStringFromValue(mdValue);
597 }
598
extract()599 bool MetadataExtractor::extract() {
600 if (!(mBitcode && mBitcodeSize) && !mModule) {
601 ALOGE("Invalid/empty bitcode/module");
602 return false;
603 }
604
605 std::unique_ptr<llvm::LLVMContext> mContext;
606 bool shouldNullModule = false;
607
608 if (!mModule) {
609 mContext.reset(new llvm::LLVMContext());
610 std::unique_ptr<llvm::MemoryBuffer> MEM(
611 llvm::MemoryBuffer::getMemBuffer(
612 llvm::StringRef(mBitcode, mBitcodeSize), "", false));
613 std::string error;
614
615 llvm::ErrorOr<std::unique_ptr<llvm::Module> > errval =
616 llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(), *mContext);
617 if (std::error_code ec = errval.getError()) {
618 ALOGE("Could not parse bitcode file");
619 ALOGE("%s", ec.message().c_str());
620 return false;
621 }
622
623 mModule = errval.get().release();
624 shouldNullModule = true;
625 }
626
627 const llvm::NamedMDNode *ExportVarMetadata =
628 mModule->getNamedMetadata(ExportVarMetadataName);
629 const llvm::NamedMDNode *ExportFuncMetadata =
630 mModule->getNamedMetadata(ExportFuncMetadataName);
631 const llvm::NamedMDNode *ExportForEachNameMetadata =
632 mModule->getNamedMetadata(ExportForEachNameMetadataName);
633 const llvm::NamedMDNode *ExportForEachMetadata =
634 mModule->getNamedMetadata(ExportForEachMetadataName);
635 const llvm::NamedMDNode *ExportReduceMetadata =
636 mModule->getNamedMetadata(ExportReduceMetadataName);
637 const llvm::NamedMDNode *PragmaMetadata =
638 mModule->getNamedMetadata(PragmaMetadataName);
639 const llvm::NamedMDNode *ObjectSlotMetadata =
640 mModule->getNamedMetadata(ObjectSlotMetadataName);
641 const llvm::NamedMDNode *ThreadableMetadata =
642 mModule->getNamedMetadata(ThreadableMetadataName);
643 const llvm::NamedMDNode *ChecksumMetadata =
644 mModule->getNamedMetadata(ChecksumMetadataName);
645 const llvm::NamedMDNode *DebugInfoMetadata =
646 mModule->getNamedMetadata(DebugInfoMetadataName);
647
648 if (!populateNameMetadata(ExportVarMetadata, mExportVarNameList,
649 mExportVarCount)) {
650 ALOGE("Could not populate export variable metadata");
651 goto err;
652 }
653
654 if (!populateNameMetadata(ExportFuncMetadata, mExportFuncNameList,
655 mExportFuncCount)) {
656 ALOGE("Could not populate export function metadata");
657 goto err;
658 }
659
660 if (!populateForEachMetadata(ExportForEachNameMetadata,
661 ExportForEachMetadata)) {
662 ALOGE("Could not populate ForEach signature metadata");
663 goto err;
664 }
665
666 if (!populateReduceMetadata(ExportReduceMetadata)) {
667 ALOGE("Could not populate export general reduction metadata");
668 goto err;
669 }
670
671 populatePragmaMetadata(PragmaMetadata);
672
673 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
674 ALOGE("Could not populate object slot metadata");
675 goto err;
676 }
677
678 readThreadableFlag(ThreadableMetadata);
679 readBuildChecksumMetadata(ChecksumMetadata);
680
681 mHasDebugInfo = DebugInfoMetadata != nullptr;
682
683 if (shouldNullModule) {
684 mModule = nullptr;
685 }
686 return true;
687
688 err:
689 if (shouldNullModule) {
690 mModule = nullptr;
691 }
692 return false;
693 }
694
695 } // namespace bcinfo
696