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