blob: 439d12198daccbbf2a06e68275fdf64628e368fb [file] [log] [blame]
Stephen Hines932bc6e2011-07-27 16:26:26 -07001/*
Stephen Hinescc366e52012-02-21 17:22:04 -08002 * Copyright 2011-2012, The Android Open Source Project
Stephen Hines932bc6e2011-07-27 16:26:26 -07003 *
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
Stephen Hinesb67c9e72012-03-22 11:02:48 -070019#include "bcinfo/BitcodeWrapper.h"
Stephen Hinesfb81ec12015-05-18 20:04:23 -070020#include "rsDefines.h"
Stephen Hinesb67c9e72012-03-22 11:02:48 -070021
Stephen Hines932bc6e2011-07-27 16:26:26 -070022#define LOG_TAG "bcinfo"
Mark Salyzynd5c69012017-01-10 14:27:14 -080023#include <log/log.h>
Stephen Hines932bc6e2011-07-27 16:26:26 -070024
David Grosscf5afcb2017-03-20 15:23:26 -070025#include "Assert.h"
26
Stephen Hines932bc6e2011-07-27 16:26:26 -070027#include "llvm/Bitcode/ReaderWriter.h"
Stephen Hinesb730e232013-01-09 15:31:36 -080028#include "llvm/IR/Constants.h"
29#include "llvm/IR/LLVMContext.h"
30#include "llvm/IR/Module.h"
Chris Wailesa6681822014-07-11 15:15:46 -070031#include "llvm/IR/Function.h"
Stephen Hines932bc6e2011-07-27 16:26:26 -070032#include "llvm/Support/MemoryBuffer.h"
33
Miao Wang110b1c12017-03-03 12:20:24 -080034#ifdef __ANDROID__
35#include "Properties.h"
36#endif
37
Stephen Hines932bc6e2011-07-27 16:26:26 -070038#include <cstdlib>
39
40namespace bcinfo {
41
Stephen Hines1bd9f622015-03-18 14:53:10 -070042namespace {
43
Stephen Hinese1c7d292015-04-15 13:20:00 -070044llvm::StringRef getStringOperand(const llvm::Metadata *node) {
45 if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
Stephen Hines1bd9f622015-03-18 14:53:10 -070046 return mds->getString();
47 }
48 return llvm::StringRef();
49}
Stephen Hinese1c7d292015-04-15 13:20:00 -070050
51bool 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
Matt Wala1895ac12015-07-16 15:34:29 -070062const 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;
Stephen Hines1bd9f622015-03-18 14:53:10 -070068}
69
David Gross79e1a052016-01-11 14:42:51 -080070const 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
Matt Wala1895ac12015-07-16 15:34:29 -070077// 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.
100bool 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
Stephen Hines932bc6e2011-07-27 16:26:26 -0700138// Name of metadata node where pragma info resides (should be synced with
139// slang.cpp)
140static 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)
144static 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)
148static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
149
Stephen Hinescc366e52012-02-21 17:22:04 -0800150// Name of metadata node where exported ForEach name information resides
151// (should be synced with slang_rs_metadata.h)
152static const llvm::StringRef ExportForEachNameMetadataName =
153 "#rs_export_foreach_name";
154
Stephen Hines33f8fe22011-08-17 12:56:22 -0700155// Name of metadata node where exported ForEach signature information resides
156// (should be synced with slang_rs_metadata.h)
157static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
158
David Gross79e1a052016-01-11 14:42:51 -0800159// Name of metadata node where exported general reduce information resides
160// (should be synced with slang_rs_metadata.h)
David Grossa48ea362016-06-02 14:46:55 -0700161static const llvm::StringRef ExportReduceMetadataName = "#rs_export_reduce";
David Gross79e1a052016-01-11 14:42:51 -0800162
Stephen Hines932bc6e2011-07-27 16:26:26 -0700163// Name of metadata node where RS object slot info resides (should be
164// synced with slang_rs_metadata.h)
165static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
166
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800167static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
Stephen Hines932bc6e2011-07-27 16:26:26 -0700168
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800169// Name of metadata node where the checksum for this build is stored. (should
170// be synced with libbcc/lib/Core/Source.cpp)
171static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
172
Dean De Leofff398d2015-11-25 13:00:31 +0000173// 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.
176static const llvm::StringRef DebugInfoMetadataName = "llvm.dbg.cu";
177
David Grosscf5afcb2017-03-20 15:23:26 -0700178const char MetadataExtractor::kWrapperMetadataName[] = "#rs_wrapper";
179
Stephen Hines932bc6e2011-07-27 16:26:26 -0700180MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
Chris Wailes900c6c12014-08-13 15:40:00 -0700181 : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
Stephen Hines569986d2012-03-09 19:58:45 -0800182 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
David Grossa48ea362016-06-02 14:46:55 -0700183 mExportReduceCount(0), mExportVarNameList(nullptr),
Matt Wala1895ac12015-07-16 15:34:29 -0700184 mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
185 mExportForEachSignatureList(nullptr),
David Grossa48ea362016-06-02 14:46:55 -0700186 mExportForEachInputCountList(nullptr),
187 mExportReduceList(nullptr),
Matt Wala1895ac12015-07-16 15:34:29 -0700188 mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
189 mObjectSlotCount(0), mObjectSlotList(nullptr),
190 mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
Dean De Leofff398d2015-11-25 13:00:31 +0000191 mBuildChecksum(nullptr), mHasDebugInfo(false) {
Stephen Hinesb67c9e72012-03-22 11:02:48 -0700192 BitcodeWrapper wrapper(bitcode, bitcodeSize);
193 mCompilerVersion = wrapper.getCompilerVersion();
194 mOptimizationLevel = wrapper.getOptimizationLevel();
Stephen Hines569986d2012-03-09 19:58:45 -0800195}
196
Stephen Hines569986d2012-03-09 19:58:45 -0800197MetadataExtractor::MetadataExtractor(const llvm::Module *module)
Matt Wala1895ac12015-07-16 15:34:29 -0700198 : mModule(module), mBitcode(nullptr), mBitcodeSize(0),
199 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
David Grossa48ea362016-06-02 14:46:55 -0700200 mExportReduceCount(0), mExportVarNameList(nullptr),
Matt Wala1895ac12015-07-16 15:34:29 -0700201 mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
202 mExportForEachSignatureList(nullptr),
David Grossa48ea362016-06-02 14:46:55 -0700203 mExportForEachInputCountList(nullptr),
204 mExportReduceList(nullptr),
Matt Wala1895ac12015-07-16 15:34:29 -0700205 mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
206 mObjectSlotCount(0), mObjectSlotList(nullptr),
207 mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
208 mBuildChecksum(nullptr) {
David Grosscf5afcb2017-03-20 15:23:26 -0700209 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);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700217}
218
219
220MetadataExtractor::~MetadataExtractor() {
Stephen Hines569986d2012-03-09 19:58:45 -0800221 if (mExportVarNameList) {
222 for (size_t i = 0; i < mExportVarCount; i++) {
223 delete [] mExportVarNameList[i];
Chris Wailes900c6c12014-08-13 15:40:00 -0700224 mExportVarNameList[i] = nullptr;
Stephen Hines569986d2012-03-09 19:58:45 -0800225 }
226 }
227 delete [] mExportVarNameList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700228 mExportVarNameList = nullptr;
Stephen Hines569986d2012-03-09 19:58:45 -0800229
230 if (mExportFuncNameList) {
231 for (size_t i = 0; i < mExportFuncCount; i++) {
232 delete [] mExportFuncNameList[i];
Chris Wailes900c6c12014-08-13 15:40:00 -0700233 mExportFuncNameList[i] = nullptr;
Stephen Hines569986d2012-03-09 19:58:45 -0800234 }
235 }
236 delete [] mExportFuncNameList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700237 mExportFuncNameList = nullptr;
Stephen Hines569986d2012-03-09 19:58:45 -0800238
Stephen Hinescc366e52012-02-21 17:22:04 -0800239 if (mExportForEachNameList) {
240 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
241 delete [] mExportForEachNameList[i];
Chris Wailes900c6c12014-08-13 15:40:00 -0700242 mExportForEachNameList[i] = nullptr;
Stephen Hinescc366e52012-02-21 17:22:04 -0800243 }
244 }
245 delete [] mExportForEachNameList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700246 mExportForEachNameList = nullptr;
Stephen Hinescc366e52012-02-21 17:22:04 -0800247
Stephen Hines33f8fe22011-08-17 12:56:22 -0700248 delete [] mExportForEachSignatureList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700249 mExportForEachSignatureList = nullptr;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700250
David Gross79e1a052016-01-11 14:42:51 -0800251 delete [] mExportForEachInputCountList;
252 mExportForEachInputCountList = nullptr;
253
David Grossa48ea362016-06-02 14:46:55 -0700254 delete [] mExportReduceList;
255 mExportReduceList = nullptr;
David Gross79e1a052016-01-11 14:42:51 -0800256
Stephen Hinescc366e52012-02-21 17:22:04 -0800257 for (size_t i = 0; i < mPragmaCount; i++) {
258 if (mPragmaKeyList) {
259 delete [] mPragmaKeyList[i];
Chris Wailes900c6c12014-08-13 15:40:00 -0700260 mPragmaKeyList[i] = nullptr;
Stephen Hinescc366e52012-02-21 17:22:04 -0800261 }
262 if (mPragmaValueList) {
263 delete [] mPragmaValueList[i];
Chris Wailes900c6c12014-08-13 15:40:00 -0700264 mPragmaValueList[i] = nullptr;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700265 }
266 }
267 delete [] mPragmaKeyList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700268 mPragmaKeyList = nullptr;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700269 delete [] mPragmaValueList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700270 mPragmaValueList = nullptr;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700271
272 delete [] mObjectSlotList;
Chris Wailes900c6c12014-08-13 15:40:00 -0700273 mObjectSlotList = nullptr;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700274
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800275 delete [] mBuildChecksum;
276
Stephen Hines932bc6e2011-07-27 16:26:26 -0700277 return;
278}
279
280
281bool 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
George Burgess IV156465e2018-04-24 16:38:13 -0700293 std::unique_ptr<uint32_t[]> TmpSlotList(new uint32_t[mObjectSlotCount]());
Stephen Hines932bc6e2011-07-27 16:26:26 -0700294 for (size_t i = 0; i < mObjectSlotCount; i++) {
295 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
Chris Wailes900c6c12014-08-13 15:40:00 -0700296 if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
Stephen Hinese1c7d292015-04-15 13:20:00 -0700297 if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
298 ALOGE("Non-integer object slot value");
299 return false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700300 }
Stephen Hinese1c7d292015-04-15 13:20:00 -0700301 } else {
302 ALOGE("Corrupt object slot information");
303 return false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700304 }
305 }
306
George Burgess IV156465e2018-04-24 16:38:13 -0700307 delete [] mObjectSlotList;
308 mObjectSlotList = TmpSlotList.release();
Stephen Hines932bc6e2011-07-27 16:26:26 -0700309 return true;
310}
311
312
Stephen Hines932bc6e2011-07-27 16:26:26 -0700313void MetadataExtractor::populatePragmaMetadata(
314 const llvm::NamedMDNode *PragmaMetadata) {
315 if (!PragmaMetadata) {
316 return;
317 }
318
319 mPragmaCount = PragmaMetadata->getNumOperands();
320 if (!mPragmaCount) {
321 return;
322 }
323
Stephen Hines569986d2012-03-09 19:58:45 -0800324 const char **TmpKeyList = new const char*[mPragmaCount];
325 const char **TmpValueList = new const char*[mPragmaCount];
Stephen Hines932bc6e2011-07-27 16:26:26 -0700326
327 for (size_t i = 0; i < mPragmaCount; i++) {
328 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
Chris Wailes900c6c12014-08-13 15:40:00 -0700329 if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
Stephen Hines1bd9f622015-03-18 14:53:10 -0700330 llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
Stephen Hines569986d2012-03-09 19:58:45 -0800331 TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
Stephen Hines1bd9f622015-03-18 14:53:10 -0700332 llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
Stephen Hines569986d2012-03-09 19:58:45 -0800333 TmpValueList[i] = createStringFromValue(PragmaValueMDS);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700334 }
335 }
336
Stephen Hines569986d2012-03-09 19:58:45 -0800337 mPragmaKeyList = TmpKeyList;
338 mPragmaValueList = TmpValueList;
339
Stephen Hinese1fd8042012-03-27 11:03:46 -0700340 // Check to see if we have any FP precision-related pragmas.
341 std::string Relaxed("rs_fp_relaxed");
342 std::string Imprecise("rs_fp_imprecise");
Stephen Hines32c56ec2012-06-01 15:26:30 -0700343 std::string Full("rs_fp_full");
Stephen Hinese1fd8042012-03-27 11:03:46 -0700344 bool RelaxedPragmaSeen = false;
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700345 bool FullPragmaSeen = false;
Stephen Hinese1fd8042012-03-27 11:03:46 -0700346 for (size_t i = 0; i < mPragmaCount; i++) {
347 if (!Relaxed.compare(mPragmaKeyList[i])) {
Stephen Hinese1fd8042012-03-27 11:03:46 -0700348 RelaxedPragmaSeen = true;
349 } else if (!Imprecise.compare(mPragmaKeyList[i])) {
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700350 ALOGW("rs_fp_imprecise is deprecated. Assuming rs_fp_relaxed instead.");
351 RelaxedPragmaSeen = true;
352 } else if (!Full.compare(mPragmaKeyList[i])) {
353 FullPragmaSeen = true;
Stephen Hinese1fd8042012-03-27 11:03:46 -0700354 }
355 }
356
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700357 if (RelaxedPragmaSeen && FullPragmaSeen) {
358 ALOGE("Full and relaxed precision specified at the same time!");
Stephen Hinese1fd8042012-03-27 11:03:46 -0700359 }
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700360 mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
Stephen Hinese1fd8042012-03-27 11:03:46 -0700361
Elliott Hughesfe0de782015-08-12 15:09:33 -0700362#ifdef __ANDROID__
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700363 // Provide an override for precsiion via adb shell setprop
Stephen Hines32c56ec2012-06-01 15:26:30 -0700364 // adb shell setprop debug.rs.precision rs_fp_full
365 // adb shell setprop debug.rs.precision rs_fp_relaxed
366 // adb shell setprop debug.rs.precision rs_fp_imprecise
Miao Wang110b1c12017-03-03 12:20:24 -0800367 char PrecisionPropBuf[PROP_VALUE_MAX];
Stephen Hines32c56ec2012-06-01 15:26:30 -0700368 const std::string PrecisionPropName("debug.rs.precision");
369 property_get("debug.rs.precision", PrecisionPropBuf, "");
370 if (PrecisionPropBuf[0]) {
371 if (!Relaxed.compare(PrecisionPropBuf)) {
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700372 ALOGI("Switching to RS FP relaxed mode via setprop");
Stephen Hines32c56ec2012-06-01 15:26:30 -0700373 mRSFloatPrecision = RS_FP_Relaxed;
374 } else if (!Imprecise.compare(PrecisionPropBuf)) {
Chris Wailes900c6c12014-08-13 15:40:00 -0700375 ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
376 "specified but is deprecated ");
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700377 mRSFloatPrecision = RS_FP_Relaxed;
Stephen Hines32c56ec2012-06-01 15:26:30 -0700378 } else if (!Full.compare(PrecisionPropBuf)) {
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700379 ALOGI("Switching to RS FP full mode via setprop");
Stephen Hines32c56ec2012-06-01 15:26:30 -0700380 mRSFloatPrecision = RS_FP_Full;
Jean-Luc Brouillet5f2e6b92014-07-08 11:10:03 -0700381 } else {
382 ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
Stephen Hines32c56ec2012-06-01 15:26:30 -0700383 }
384 }
Nick Kralevich85d95712013-05-22 13:49:01 -0700385#endif
Stephen Hines932bc6e2011-07-27 16:26:26 -0700386}
387
Chris Wailesa6681822014-07-11 15:15:46 -0700388uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
389 uint32_t Signature) {
390
391 if (hasForEachSignatureIn(Signature)) {
392 uint32_t OtherCount = 0;
393
394 OtherCount += hasForEachSignatureUsrData(Signature);
395 OtherCount += hasForEachSignatureX(Signature);
396 OtherCount += hasForEachSignatureY(Signature);
David Gross33cda5c2015-01-30 11:41:19 -0800397 OtherCount += hasForEachSignatureZ(Signature);
398 OtherCount += hasForEachSignatureCtxt(Signature);
Chris Wailesa6681822014-07-11 15:15:46 -0700399 OtherCount += hasForEachSignatureOut(Signature) &&
400 Function->getReturnType()->isVoidTy();
401
402 return Function->arg_size() - OtherCount;
403
404 } else {
405 return 0;
406 }
407}
408
409
Stephen Hines33f8fe22011-08-17 12:56:22 -0700410bool MetadataExtractor::populateForEachMetadata(
Stephen Hinescc366e52012-02-21 17:22:04 -0800411 const llvm::NamedMDNode *Names,
412 const llvm::NamedMDNode *Signatures) {
Stephen Hines11de13e2013-06-07 11:41:18 -0700413 if (!Names && !Signatures && mCompilerVersion == 0) {
Stephen Hines0231bb02011-10-10 15:30:25 -0700414 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
415 // section for ForEach. We generate a full signature for a "root" function
416 // which means that we need to set the bottom 5 bits in the mask.
417 mExportForEachSignatureCount = 1;
Stephen Hinescc366e52012-02-21 17:22:04 -0800418 char **TmpNameList = new char*[mExportForEachSignatureCount];
Stephen Hinesfb81ec12015-05-18 20:04:23 -0700419 size_t RootLen = strlen(kRoot) + 1;
420 TmpNameList[0] = new char[RootLen];
421 strncpy(TmpNameList[0], kRoot, RootLen);
Stephen Hinescc366e52012-02-21 17:22:04 -0800422
Stephen Hines0231bb02011-10-10 15:30:25 -0700423 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
424 TmpSigList[0] = 0x1f;
Stephen Hines569986d2012-03-09 19:58:45 -0800425
Stephen Hinescc366e52012-02-21 17:22:04 -0800426 mExportForEachNameList = (const char**)TmpNameList;
Stephen Hines0231bb02011-10-10 15:30:25 -0700427 mExportForEachSignatureList = TmpSigList;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700428 return true;
429 }
430
Stephen Hines109be672012-06-06 16:01:59 -0700431 if (Signatures) {
432 mExportForEachSignatureCount = Signatures->getNumOperands();
433 if (!mExportForEachSignatureCount) {
434 return true;
435 }
436 } else {
437 mExportForEachSignatureCount = 0;
Chris Wailes900c6c12014-08-13 15:40:00 -0700438 mExportForEachSignatureList = nullptr;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700439 return true;
440 }
441
George Burgess IV156465e2018-04-24 16:38:13 -0700442 std::unique_ptr<uint32_t[]> TmpSigList(new uint32_t[mExportForEachSignatureCount]);
443 std::unique_ptr<const char *[]> TmpNameList(new const char*[mExportForEachSignatureCount]);
444 std::unique_ptr<uint32_t[]> TmpInputCountList(new uint32_t[mExportForEachSignatureCount]);
Stephen Hines33f8fe22011-08-17 12:56:22 -0700445
446 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
Stephen Hinescc366e52012-02-21 17:22:04 -0800447 llvm::MDNode *SigNode = Signatures->getOperand(i);
Chris Wailes900c6c12014-08-13 15:40:00 -0700448 if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
Stephen Hinese1c7d292015-04-15 13:20:00 -0700449 if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
450 ALOGE("Non-integer signature value");
451 return false;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700452 }
Stephen Hinese1c7d292015-04-15 13:20:00 -0700453 } else {
454 ALOGE("Corrupt signature information");
455 return false;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700456 }
457 }
458
Stephen Hines109be672012-06-06 16:01:59 -0700459 if (Names) {
460 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
461 llvm::MDNode *Name = Names->getOperand(i);
Chris Wailes900c6c12014-08-13 15:40:00 -0700462 if (Name != nullptr && Name->getNumOperands() == 1) {
Stephen Hines109be672012-06-06 16:01:59 -0700463 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
Chris Wailesa6681822014-07-11 15:15:46 -0700464
David Gross8d7fe842016-02-18 14:00:32 -0800465 // Note that looking up the function by name can fail: One of
466 // the uses of MetadataExtractor is as part of the
467 // RSEmbedInfoPass, which bcc_compat runs sufficiently late in
468 // the phase order that RSKernelExpandPass has already run and
469 // the original (UNexpanded) kernel function (TmpNameList[i])
470 // may have been deleted as having no references (if it has
471 // been inlined into the expanded kernel function and is
472 // otherwise unreferenced).
Chris Wailes900c6c12014-08-13 15:40:00 -0700473 llvm::Function *Func =
474 mModule->getFunction(llvm::StringRef(TmpNameList[i]));
Chris Wailesa6681822014-07-11 15:15:46 -0700475
Chris Wailes900c6c12014-08-13 15:40:00 -0700476 TmpInputCountList[i] = (Func != nullptr) ?
Chris Wailesa6681822014-07-11 15:15:46 -0700477 calculateNumInputs(Func, TmpSigList[i]) : 0;
Stephen Hines109be672012-06-06 16:01:59 -0700478 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800479 }
Stephen Hines109be672012-06-06 16:01:59 -0700480 } else {
481 if (mExportForEachSignatureCount != 1) {
Stephen Hines3e4cac42012-06-07 01:57:15 -0700482 ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
Stephen Hines109be672012-06-06 16:01:59 -0700483 mExportForEachSignatureCount);
484 }
485 char *RootName = new char[5];
486 strncpy(RootName, "root", 5);
487 TmpNameList[0] = RootName;
Stephen Hinescc366e52012-02-21 17:22:04 -0800488 }
489
George Burgess IV156465e2018-04-24 16:38:13 -0700490 delete [] mExportForEachNameList;
491 mExportForEachNameList = TmpNameList.release();
492
493 delete [] mExportForEachSignatureList;
494 mExportForEachSignatureList = TmpSigList.release();
495
496 delete [] mExportForEachInputCountList;
497 mExportForEachInputCountList = TmpInputCountList.release();
Stephen Hines569986d2012-03-09 19:58:45 -0800498
Stephen Hines33f8fe22011-08-17 12:56:22 -0700499 return true;
500}
501
502
David Grossa48ea362016-06-02 14:46:55 -0700503bool MetadataExtractor::populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata) {
504 mExportReduceCount = 0;
505 mExportReduceList = nullptr;
David Gross79e1a052016-01-11 14:42:51 -0800506
David Grossa48ea362016-06-02 14:46:55 -0700507 if (!ReduceMetadata || !(mExportReduceCount = ReduceMetadata->getNumOperands()))
David Gross79e1a052016-01-11 14:42:51 -0800508 return true;
509
Luis Lozanod389fdd2016-10-18 17:18:56 -0700510 std::unique_ptr<Reduce[]> TmpReduceList(new Reduce[mExportReduceCount]);
David Gross79e1a052016-01-11 14:42:51 -0800511
David Grossa48ea362016-06-02 14:46:55 -0700512 for (size_t i = 0; i < mExportReduceCount; i++) {
513 llvm::MDNode *Node = ReduceMetadata->getOperand(i);
David Gross79e1a052016-01-11 14:42:51 -0800514 if (!Node || Node->getNumOperands() < 3) {
515 ALOGE("Missing reduce metadata");
516 return false;
517 }
518
David Grossa48ea362016-06-02 14:46:55 -0700519 TmpReduceList[i].mReduceName = createStringFromValue(Node->getOperand(0));
David Gross79e1a052016-01-11 14:42:51 -0800520
David Grossa48ea362016-06-02 14:46:55 -0700521 if (!extractUIntFromMetadataString(&TmpReduceList[i].mAccumulatorDataSize,
David Gross79e1a052016-01-11 14:42:51 -0800522 Node->getOperand(1))) {
523 ALOGE("Non-integer accumulator data size value in reduce metadata");
524 return false;
525 }
526
527 llvm::MDNode *AccumulatorNode = llvm::dyn_cast<llvm::MDNode>(Node->getOperand(2));
528 if (!AccumulatorNode || AccumulatorNode->getNumOperands() != 2) {
529 ALOGE("Malformed accumulator node in reduce metadata");
530 return false;
531 }
David Grossa48ea362016-06-02 14:46:55 -0700532 TmpReduceList[i].mAccumulatorName = createStringFromValue(AccumulatorNode->getOperand(0));
533 if (!extractUIntFromMetadataString(&TmpReduceList[i].mSignature,
David Gross79e1a052016-01-11 14:42:51 -0800534 AccumulatorNode->getOperand(1))) {
535 ALOGE("Non-integer signature value in reduce metadata");
536 return false;
537 }
David Gross8d7fe842016-02-18 14:00:32 -0800538 // Note that looking up the function by name can fail: One of the
539 // uses of MetadataExtractor is as part of the RSEmbedInfoPass,
540 // which bcc_compat runs sufficiently late in the phase order that
541 // RSKernelExpandPass has already run and the original
542 // (UNexpanded) accumulator function (mAccumulatorName) may have
543 // been deleted as having no references (if it has been inlined
544 // into the expanded accumulator function and is otherwise
545 // unreferenced).
David Gross79e1a052016-01-11 14:42:51 -0800546 llvm::Function *Func =
David Grossa48ea362016-06-02 14:46:55 -0700547 mModule->getFunction(llvm::StringRef(TmpReduceList[i].mAccumulatorName));
David Gross79e1a052016-01-11 14:42:51 -0800548 // Why calculateNumInputs() - 1? The "-1" is because we don't
549 // want to treat the accumulator argument as an input.
David Grossa48ea362016-06-02 14:46:55 -0700550 TmpReduceList[i].mInputCount = (Func ? calculateNumInputs(Func, TmpReduceList[i].mSignature) - 1 : 0);
David Gross79e1a052016-01-11 14:42:51 -0800551
David Grossa48ea362016-06-02 14:46:55 -0700552 TmpReduceList[i].mInitializerName = createStringFromOptionalValue(Node, 3);
553 TmpReduceList[i].mCombinerName = createStringFromOptionalValue(Node, 4);
554 TmpReduceList[i].mOutConverterName = createStringFromOptionalValue(Node, 5);
555 TmpReduceList[i].mHalterName = createStringFromOptionalValue(Node, 6);
David Gross79e1a052016-01-11 14:42:51 -0800556 }
557
Luis Lozanod389fdd2016-10-18 17:18:56 -0700558 mExportReduceList = TmpReduceList.release();
David Gross79e1a052016-01-11 14:42:51 -0800559 return true;
560}
561
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800562void MetadataExtractor::readThreadableFlag(
563 const llvm::NamedMDNode *ThreadableMetadata) {
564
565 // Scripts are threadable by default. If we read a valid metadata value for
566 // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
567 // threadable. All other exception paths retain the default value.
568
569 mIsThreadable = true;
570 if (ThreadableMetadata == nullptr)
571 return;
572
573 llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
574 if (mdNode == nullptr)
575 return;
576
Stephen Hines1bd9f622015-03-18 14:53:10 -0700577 llvm::Metadata *mdValue = mdNode->getOperand(0);
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800578 if (mdValue == nullptr)
579 return;
580
Stephen Hinese1c7d292015-04-15 13:20:00 -0700581 if (getStringOperand(mdValue) == "no")
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800582 mIsThreadable = false;
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800583}
584
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800585void MetadataExtractor::readBuildChecksumMetadata(
586 const llvm::NamedMDNode *ChecksumMetadata) {
587
588 if (ChecksumMetadata == nullptr)
589 return;
590
Stephen Hines1bd9f622015-03-18 14:53:10 -0700591 llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800592 if (mdNode == nullptr)
593 return;
594
Stephen Hines1bd9f622015-03-18 14:53:10 -0700595 llvm::Metadata *mdValue = mdNode->getOperand(0);
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800596 if (mdValue == nullptr)
597 return;
598
599 mBuildChecksum = createStringFromValue(mdValue);
600}
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800601
Stephen Hines932bc6e2011-07-27 16:26:26 -0700602bool MetadataExtractor::extract() {
Stephen Hines569986d2012-03-09 19:58:45 -0800603 if (!(mBitcode && mBitcodeSize) && !mModule) {
604 ALOGE("Invalid/empty bitcode/module");
Stephen Hines932bc6e2011-07-27 16:26:26 -0700605 return false;
606 }
607
Stephen Hinesd0993af2014-07-15 16:49:25 -0700608 std::unique_ptr<llvm::LLVMContext> mContext;
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800609 bool shouldNullModule = false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700610
Stephen Hines569986d2012-03-09 19:58:45 -0800611 if (!mModule) {
612 mContext.reset(new llvm::LLVMContext());
Stephen Hinesd0993af2014-07-15 16:49:25 -0700613 std::unique_ptr<llvm::MemoryBuffer> MEM(
Stephen Hines569986d2012-03-09 19:58:45 -0800614 llvm::MemoryBuffer::getMemBuffer(
Stephen Hinese708ffe2012-05-03 15:18:49 -0700615 llvm::StringRef(mBitcode, mBitcodeSize), "", false));
Stephen Hines569986d2012-03-09 19:58:45 -0800616 std::string error;
617
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800618 llvm::ErrorOr<std::unique_ptr<llvm::Module> > errval =
619 llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(), *mContext);
Stephen Hinesd0993af2014-07-15 16:49:25 -0700620 if (std::error_code ec = errval.getError()) {
Tim Murrayc2074ca2014-04-08 15:39:08 -0700621 ALOGE("Could not parse bitcode file");
622 ALOGE("%s", ec.message().c_str());
623 return false;
Stephen Hines569986d2012-03-09 19:58:45 -0800624 }
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800625
626 mModule = errval.get().release();
627 shouldNullModule = true;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700628 }
629
630 const llvm::NamedMDNode *ExportVarMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800631 mModule->getNamedMetadata(ExportVarMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700632 const llvm::NamedMDNode *ExportFuncMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800633 mModule->getNamedMetadata(ExportFuncMetadataName);
Stephen Hinescc366e52012-02-21 17:22:04 -0800634 const llvm::NamedMDNode *ExportForEachNameMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800635 mModule->getNamedMetadata(ExportForEachNameMetadataName);
Stephen Hines33f8fe22011-08-17 12:56:22 -0700636 const llvm::NamedMDNode *ExportForEachMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800637 mModule->getNamedMetadata(ExportForEachMetadataName);
David Grossa48ea362016-06-02 14:46:55 -0700638 const llvm::NamedMDNode *ExportReduceMetadata =
639 mModule->getNamedMetadata(ExportReduceMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700640 const llvm::NamedMDNode *PragmaMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800641 mModule->getNamedMetadata(PragmaMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700642 const llvm::NamedMDNode *ObjectSlotMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800643 mModule->getNamedMetadata(ObjectSlotMetadataName);
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800644 const llvm::NamedMDNode *ThreadableMetadata =
645 mModule->getNamedMetadata(ThreadableMetadataName);
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800646 const llvm::NamedMDNode *ChecksumMetadata =
647 mModule->getNamedMetadata(ChecksumMetadataName);
Dean De Leofff398d2015-11-25 13:00:31 +0000648 const llvm::NamedMDNode *DebugInfoMetadata =
649 mModule->getNamedMetadata(DebugInfoMetadataName);
Daniel Malea094881f2011-12-14 17:39:16 -0500650
Matt Wala1895ac12015-07-16 15:34:29 -0700651 if (!populateNameMetadata(ExportVarMetadata, mExportVarNameList,
652 mExportVarCount)) {
Stephen Hines569986d2012-03-09 19:58:45 -0800653 ALOGE("Could not populate export variable metadata");
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800654 goto err;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700655 }
656
Matt Wala1895ac12015-07-16 15:34:29 -0700657 if (!populateNameMetadata(ExportFuncMetadata, mExportFuncNameList,
658 mExportFuncCount)) {
Stephen Hines569986d2012-03-09 19:58:45 -0800659 ALOGE("Could not populate export function metadata");
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800660 goto err;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700661 }
662
Stephen Hinescc366e52012-02-21 17:22:04 -0800663 if (!populateForEachMetadata(ExportForEachNameMetadata,
664 ExportForEachMetadata)) {
Steve Block10c14122012-01-08 10:15:06 +0000665 ALOGE("Could not populate ForEach signature metadata");
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800666 goto err;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700667 }
668
David Grossa48ea362016-06-02 14:46:55 -0700669 if (!populateReduceMetadata(ExportReduceMetadata)) {
David Gross79e1a052016-01-11 14:42:51 -0800670 ALOGE("Could not populate export general reduction metadata");
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800671 goto err;
David Gross79e1a052016-01-11 14:42:51 -0800672 }
673
Stephen Hines932bc6e2011-07-27 16:26:26 -0700674 populatePragmaMetadata(PragmaMetadata);
675
676 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
Steve Block10c14122012-01-08 10:15:06 +0000677 ALOGE("Could not populate object slot metadata");
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800678 goto err;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700679 }
680
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800681 readThreadableFlag(ThreadableMetadata);
Pirama Arumuga Nainar51ee77b2015-02-19 16:33:27 -0800682 readBuildChecksumMetadata(ChecksumMetadata);
Pirama Arumuga Nainar9fe081b2015-01-27 14:09:19 -0800683
Dean De Leofff398d2015-11-25 13:00:31 +0000684 mHasDebugInfo = DebugInfoMetadata != nullptr;
685
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800686 if (shouldNullModule) {
687 mModule = nullptr;
688 }
Stephen Hines932bc6e2011-07-27 16:26:26 -0700689 return true;
Pirama Arumuga Nainar8e908932016-03-06 23:05:45 -0800690
691err:
692 if (shouldNullModule) {
693 mModule = nullptr;
694 }
695 return false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700696}
697
698} // namespace bcinfo