blob: 98aad18185929348dae0faf76d923ab021349e1a [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"
20
Stephen Hines932bc6e2011-07-27 16:26:26 -070021#define LOG_TAG "bcinfo"
22#include <cutils/log.h>
Stephen Hines32c56ec2012-06-01 15:26:30 -070023#include <cutils/properties.h>
Stephen Hines932bc6e2011-07-27 16:26:26 -070024
25#include "llvm/ADT/OwningPtr.h"
26#include "llvm/Bitcode/ReaderWriter.h"
Daniel Malea094881f2011-12-14 17:39:16 -050027#include "llvm/Constants.h"
Stephen Hines932bc6e2011-07-27 16:26:26 -070028#include "llvm/LLVMContext.h"
29#include "llvm/Module.h"
30#include "llvm/Support/MemoryBuffer.h"
31
32#include <cstdlib>
33
34namespace bcinfo {
35
36// Name of metadata node where pragma info resides (should be synced with
37// slang.cpp)
38static const llvm::StringRef PragmaMetadataName = "#pragma";
39
40// Name of metadata node where exported variable names reside (should be
41// synced with slang_rs_metadata.h)
42static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
43
44// Name of metadata node where exported function names reside (should be
45// synced with slang_rs_metadata.h)
46static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
47
Stephen Hinescc366e52012-02-21 17:22:04 -080048// Name of metadata node where exported ForEach name information resides
49// (should be synced with slang_rs_metadata.h)
50static const llvm::StringRef ExportForEachNameMetadataName =
51 "#rs_export_foreach_name";
52
Stephen Hines33f8fe22011-08-17 12:56:22 -070053// Name of metadata node where exported ForEach signature information resides
54// (should be synced with slang_rs_metadata.h)
55static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
56
Stephen Hines932bc6e2011-07-27 16:26:26 -070057// Name of metadata node where RS object slot info resides (should be
58// synced with slang_rs_metadata.h)
59static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
60
61
62MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
Stephen Hines569986d2012-03-09 19:58:45 -080063 : mModule(NULL), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
64 mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
65 mExportVarNameList(NULL), mExportFuncNameList(NULL),
66 mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
67 mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
Stephen Hinesa7e5c8f2012-03-28 12:58:24 -070068 mObjectSlotCount(0), mObjectSlotList(NULL),
Stephen Hinese1fd8042012-03-27 11:03:46 -070069 mRSFloatPrecision(RS_FP_Full) {
Stephen Hinesb67c9e72012-03-22 11:02:48 -070070 BitcodeWrapper wrapper(bitcode, bitcodeSize);
71 mCompilerVersion = wrapper.getCompilerVersion();
72 mOptimizationLevel = wrapper.getOptimizationLevel();
Stephen Hines569986d2012-03-09 19:58:45 -080073}
74
75
76MetadataExtractor::MetadataExtractor(const llvm::Module *module)
77 : mModule(module), mBitcode(NULL), mBitcodeSize(0), mExportVarCount(0),
Stephen Hines33f8fe22011-08-17 12:56:22 -070078 mExportFuncCount(0), mExportForEachSignatureCount(0),
Stephen Hines569986d2012-03-09 19:58:45 -080079 mExportVarNameList(NULL), mExportFuncNameList(NULL),
Stephen Hinescc366e52012-02-21 17:22:04 -080080 mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
81 mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
Stephen Hines98abb2d2012-04-06 16:52:51 -070082 mObjectSlotCount(0), mObjectSlotList(NULL),
83 mRSFloatPrecision(RS_FP_Full) {
Stephen Hinesa7e5c8f2012-03-28 12:58:24 -070084 mCompilerVersion = 0;
85 mOptimizationLevel = 3;
Stephen Hines932bc6e2011-07-27 16:26:26 -070086}
87
88
89MetadataExtractor::~MetadataExtractor() {
Stephen Hines569986d2012-03-09 19:58:45 -080090 if (mExportVarNameList) {
91 for (size_t i = 0; i < mExportVarCount; i++) {
92 delete [] mExportVarNameList[i];
93 mExportVarNameList[i] = NULL;
94 }
95 }
96 delete [] mExportVarNameList;
97 mExportVarNameList = NULL;
98
99 if (mExportFuncNameList) {
100 for (size_t i = 0; i < mExportFuncCount; i++) {
101 delete [] mExportFuncNameList[i];
102 mExportFuncNameList[i] = NULL;
103 }
104 }
105 delete [] mExportFuncNameList;
106 mExportFuncNameList = NULL;
107
Stephen Hinescc366e52012-02-21 17:22:04 -0800108 if (mExportForEachNameList) {
109 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
110 delete [] mExportForEachNameList[i];
111 mExportForEachNameList[i] = NULL;
112 }
113 }
114 delete [] mExportForEachNameList;
115 mExportForEachNameList = NULL;
116
Stephen Hines33f8fe22011-08-17 12:56:22 -0700117 delete [] mExportForEachSignatureList;
118 mExportForEachSignatureList = NULL;
119
Stephen Hinescc366e52012-02-21 17:22:04 -0800120 for (size_t i = 0; i < mPragmaCount; i++) {
121 if (mPragmaKeyList) {
122 delete [] mPragmaKeyList[i];
123 mPragmaKeyList[i] = NULL;
124 }
125 if (mPragmaValueList) {
126 delete [] mPragmaValueList[i];
127 mPragmaValueList[i] = NULL;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700128 }
129 }
130 delete [] mPragmaKeyList;
131 mPragmaKeyList = NULL;
132 delete [] mPragmaValueList;
133 mPragmaValueList = NULL;
134
135 delete [] mObjectSlotList;
136 mObjectSlotList = NULL;
137
138 return;
139}
140
141
142bool MetadataExtractor::populateObjectSlotMetadata(
143 const llvm::NamedMDNode *ObjectSlotMetadata) {
144 if (!ObjectSlotMetadata) {
145 return true;
146 }
147
148 mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
149
150 if (!mObjectSlotCount) {
151 return true;
152 }
153
154 uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
155 memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
156
157 for (size_t i = 0; i < mObjectSlotCount; i++) {
158 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
159 if (ObjectSlot != NULL && ObjectSlot->getNumOperands() == 1) {
160 llvm::Value *SlotMDS = ObjectSlot->getOperand(0);
161 if (SlotMDS->getValueID() == llvm::Value::MDStringVal) {
162 llvm::StringRef Slot =
163 static_cast<llvm::MDString*>(SlotMDS)->getString();
164 uint32_t USlot = 0;
165 if (Slot.getAsInteger(10, USlot)) {
Steve Block10c14122012-01-08 10:15:06 +0000166 ALOGE("Non-integer object slot value '%s'", Slot.str().c_str());
Stephen Hines932bc6e2011-07-27 16:26:26 -0700167 return false;
168 }
169 TmpSlotList[i] = USlot;
170 }
171 }
172 }
173
174 mObjectSlotList = TmpSlotList;
175
176 return true;
177}
178
179
180static const char *createStringFromValue(llvm::Value *v) {
181 if (v->getValueID() != llvm::Value::MDStringVal) {
182 return NULL;
183 }
184
185 llvm::StringRef ref = static_cast<llvm::MDString*>(v)->getString();
186
187 char *c = new char[ref.size() + 1];
188 memcpy(c, ref.data(), ref.size());
189 c[ref.size()] = '\0';
190
191 return c;
192}
193
194
195void MetadataExtractor::populatePragmaMetadata(
196 const llvm::NamedMDNode *PragmaMetadata) {
197 if (!PragmaMetadata) {
198 return;
199 }
200
201 mPragmaCount = PragmaMetadata->getNumOperands();
202 if (!mPragmaCount) {
203 return;
204 }
205
Stephen Hines569986d2012-03-09 19:58:45 -0800206 const char **TmpKeyList = new const char*[mPragmaCount];
207 const char **TmpValueList = new const char*[mPragmaCount];
Stephen Hines932bc6e2011-07-27 16:26:26 -0700208
209 for (size_t i = 0; i < mPragmaCount; i++) {
210 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
211 if (Pragma != NULL && Pragma->getNumOperands() == 2) {
212 llvm::Value *PragmaKeyMDS = Pragma->getOperand(0);
Stephen Hines569986d2012-03-09 19:58:45 -0800213 TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700214 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
Stephen Hines569986d2012-03-09 19:58:45 -0800215 TmpValueList[i] = createStringFromValue(PragmaValueMDS);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700216 }
217 }
218
Stephen Hines569986d2012-03-09 19:58:45 -0800219 mPragmaKeyList = TmpKeyList;
220 mPragmaValueList = TmpValueList;
221
Stephen Hinese1fd8042012-03-27 11:03:46 -0700222 // Check to see if we have any FP precision-related pragmas.
223 std::string Relaxed("rs_fp_relaxed");
224 std::string Imprecise("rs_fp_imprecise");
Stephen Hines32c56ec2012-06-01 15:26:30 -0700225 std::string Full("rs_fp_full");
Stephen Hinese1fd8042012-03-27 11:03:46 -0700226 bool RelaxedPragmaSeen = false;
227 bool ImprecisePragmaSeen = false;
228
229 for (size_t i = 0; i < mPragmaCount; i++) {
230 if (!Relaxed.compare(mPragmaKeyList[i])) {
231 if (RelaxedPragmaSeen || ImprecisePragmaSeen) {
232 ALOGE("Multiple float precision pragmas specified!");
233 }
234 RelaxedPragmaSeen = true;
235 } else if (!Imprecise.compare(mPragmaKeyList[i])) {
236 if (RelaxedPragmaSeen || ImprecisePragmaSeen) {
237 ALOGE("Multiple float precision pragmas specified!");
238 }
239 ImprecisePragmaSeen = true;
240 }
241 }
242
243 // Imprecise is selected over Relaxed precision.
244 // In the absence of both, we stick to the default Full precision.
245 if (ImprecisePragmaSeen) {
246 mRSFloatPrecision = RS_FP_Imprecise;
247 } else if (RelaxedPragmaSeen) {
248 mRSFloatPrecision = RS_FP_Relaxed;
249 }
250
Stephen Hines32c56ec2012-06-01 15:26:30 -0700251 // Provide an override for precsion via adb shell setprop
252 // adb shell setprop debug.rs.precision rs_fp_full
253 // adb shell setprop debug.rs.precision rs_fp_relaxed
254 // adb shell setprop debug.rs.precision rs_fp_imprecise
255 char PrecisionPropBuf[PROPERTY_VALUE_MAX];
256 const std::string PrecisionPropName("debug.rs.precision");
257 property_get("debug.rs.precision", PrecisionPropBuf, "");
258 if (PrecisionPropBuf[0]) {
259 if (!Relaxed.compare(PrecisionPropBuf)) {
260 ALOGE("Switching to RS FP relaxed mode via setprop");
261 mRSFloatPrecision = RS_FP_Relaxed;
262 } else if (!Imprecise.compare(PrecisionPropBuf)) {
263 ALOGE("Switching to RS FP imprecise mode via setprop");
264 mRSFloatPrecision = RS_FP_Imprecise;
265 } else if (!Full.compare(PrecisionPropBuf)) {
266 ALOGE("Switching to RS FP full mode via setprop");
267 mRSFloatPrecision = RS_FP_Full;
268 }
269 }
270
Stephen Hines932bc6e2011-07-27 16:26:26 -0700271 return;
272}
273
274
Stephen Hines569986d2012-03-09 19:58:45 -0800275bool MetadataExtractor::populateVarNameMetadata(
276 const llvm::NamedMDNode *VarNameMetadata) {
277 if (!VarNameMetadata) {
278 return true;
279 }
280
281 mExportVarCount = VarNameMetadata->getNumOperands();
282 if (!mExportVarCount) {
283 return true;
284 }
285
286 const char **TmpNameList = new const char *[mExportVarCount];
287
288 for (size_t i = 0; i < mExportVarCount; i++) {
289 llvm::MDNode *Name = VarNameMetadata->getOperand(i);
290 if (Name != NULL && Name->getNumOperands() > 1) {
291 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
292 }
293 }
294
295 mExportVarNameList = TmpNameList;
296
297 return true;
298}
299
300
301bool MetadataExtractor::populateFuncNameMetadata(
302 const llvm::NamedMDNode *FuncNameMetadata) {
303 if (!FuncNameMetadata) {
304 return true;
305 }
306
307 mExportFuncCount = FuncNameMetadata->getNumOperands();
308 if (!mExportFuncCount) {
309 return true;
310 }
311
312 const char **TmpNameList = new const char*[mExportFuncCount];
313
314 for (size_t i = 0; i < mExportFuncCount; i++) {
315 llvm::MDNode *Name = FuncNameMetadata->getOperand(i);
316 if (Name != NULL && Name->getNumOperands() == 1) {
317 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
318 }
319 }
320
321 mExportFuncNameList = TmpNameList;
322
323 return true;
324}
325
326
Stephen Hines33f8fe22011-08-17 12:56:22 -0700327bool MetadataExtractor::populateForEachMetadata(
Stephen Hinescc366e52012-02-21 17:22:04 -0800328 const llvm::NamedMDNode *Names,
329 const llvm::NamedMDNode *Signatures) {
Stephen Hines109be672012-06-06 16:01:59 -0700330 if (!Names && !Signatures) {
Stephen Hines0231bb02011-10-10 15:30:25 -0700331 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
332 // section for ForEach. We generate a full signature for a "root" function
333 // which means that we need to set the bottom 5 bits in the mask.
334 mExportForEachSignatureCount = 1;
Stephen Hinescc366e52012-02-21 17:22:04 -0800335 char **TmpNameList = new char*[mExportForEachSignatureCount];
336 TmpNameList[0] = new char[5];
337 strncpy(TmpNameList[0], "root", 5);
338
Stephen Hines0231bb02011-10-10 15:30:25 -0700339 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
340 TmpSigList[0] = 0x1f;
Stephen Hines569986d2012-03-09 19:58:45 -0800341
Stephen Hinescc366e52012-02-21 17:22:04 -0800342 mExportForEachNameList = (const char**)TmpNameList;
Stephen Hines0231bb02011-10-10 15:30:25 -0700343 mExportForEachSignatureList = TmpSigList;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700344 return true;
345 }
346
Stephen Hines109be672012-06-06 16:01:59 -0700347 if (Signatures) {
348 mExportForEachSignatureCount = Signatures->getNumOperands();
349 if (!mExportForEachSignatureCount) {
350 return true;
351 }
352 } else {
353 mExportForEachSignatureCount = 0;
354 mExportForEachSignatureList = NULL;
Stephen Hines33f8fe22011-08-17 12:56:22 -0700355 return true;
356 }
357
358 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
Stephen Hines569986d2012-03-09 19:58:45 -0800359 const char **TmpNameList = new const char*[mExportForEachSignatureCount];
Stephen Hines33f8fe22011-08-17 12:56:22 -0700360
361 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
Stephen Hinescc366e52012-02-21 17:22:04 -0800362 llvm::MDNode *SigNode = Signatures->getOperand(i);
Stephen Hines33f8fe22011-08-17 12:56:22 -0700363 if (SigNode != NULL && SigNode->getNumOperands() == 1) {
364 llvm::Value *SigVal = SigNode->getOperand(0);
365 if (SigVal->getValueID() == llvm::Value::MDStringVal) {
366 llvm::StringRef SigString =
367 static_cast<llvm::MDString*>(SigVal)->getString();
368 uint32_t Signature = 0;
369 if (SigString.getAsInteger(10, Signature)) {
Steve Block10c14122012-01-08 10:15:06 +0000370 ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
Stephen Hines33f8fe22011-08-17 12:56:22 -0700371 return false;
372 }
373 TmpSigList[i] = Signature;
374 }
375 }
376 }
377
Stephen Hines109be672012-06-06 16:01:59 -0700378 if (Names) {
379 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
380 llvm::MDNode *Name = Names->getOperand(i);
381 if (Name != NULL && Name->getNumOperands() == 1) {
382 TmpNameList[i] = createStringFromValue(Name->getOperand(0));
383 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800384 }
Stephen Hines109be672012-06-06 16:01:59 -0700385 } else {
386 if (mExportForEachSignatureCount != 1) {
387 ALOGE("mExportForEachSignatureCount = %u, but should be 1",
388 mExportForEachSignatureCount);
389 }
390 char *RootName = new char[5];
391 strncpy(RootName, "root", 5);
392 TmpNameList[0] = RootName;
Stephen Hinescc366e52012-02-21 17:22:04 -0800393 }
394
Stephen Hines569986d2012-03-09 19:58:45 -0800395 mExportForEachNameList = TmpNameList;
396 mExportForEachSignatureList = TmpSigList;
397
Stephen Hines33f8fe22011-08-17 12:56:22 -0700398 return true;
399}
400
401
Stephen Hines932bc6e2011-07-27 16:26:26 -0700402bool MetadataExtractor::extract() {
Stephen Hines569986d2012-03-09 19:58:45 -0800403 if (!(mBitcode && mBitcodeSize) && !mModule) {
404 ALOGE("Invalid/empty bitcode/module");
Stephen Hines932bc6e2011-07-27 16:26:26 -0700405 return false;
406 }
407
Stephen Hines569986d2012-03-09 19:58:45 -0800408 llvm::OwningPtr<llvm::LLVMContext> mContext;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700409
Stephen Hines569986d2012-03-09 19:58:45 -0800410 if (!mModule) {
411 mContext.reset(new llvm::LLVMContext());
412 llvm::OwningPtr<llvm::MemoryBuffer> MEM(
413 llvm::MemoryBuffer::getMemBuffer(
Stephen Hinese708ffe2012-05-03 15:18:49 -0700414 llvm::StringRef(mBitcode, mBitcodeSize), "", false));
Stephen Hines569986d2012-03-09 19:58:45 -0800415 std::string error;
416
417 // Module ownership is handled by the context, so we don't need to free it.
418 mModule = llvm::ParseBitcodeFile(MEM.get(), *mContext, &error);
419 if (!mModule) {
420 ALOGE("Could not parse bitcode file");
421 ALOGE("%s", error.c_str());
422 return false;
423 }
Stephen Hines932bc6e2011-07-27 16:26:26 -0700424 }
425
426 const llvm::NamedMDNode *ExportVarMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800427 mModule->getNamedMetadata(ExportVarMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700428 const llvm::NamedMDNode *ExportFuncMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800429 mModule->getNamedMetadata(ExportFuncMetadataName);
Stephen Hinescc366e52012-02-21 17:22:04 -0800430 const llvm::NamedMDNode *ExportForEachNameMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800431 mModule->getNamedMetadata(ExportForEachNameMetadataName);
Stephen Hines33f8fe22011-08-17 12:56:22 -0700432 const llvm::NamedMDNode *ExportForEachMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800433 mModule->getNamedMetadata(ExportForEachMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700434 const llvm::NamedMDNode *PragmaMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800435 mModule->getNamedMetadata(PragmaMetadataName);
Stephen Hines932bc6e2011-07-27 16:26:26 -0700436 const llvm::NamedMDNode *ObjectSlotMetadata =
Stephen Hines569986d2012-03-09 19:58:45 -0800437 mModule->getNamedMetadata(ObjectSlotMetadataName);
Daniel Malea094881f2011-12-14 17:39:16 -0500438
Stephen Hines932bc6e2011-07-27 16:26:26 -0700439
Stephen Hines569986d2012-03-09 19:58:45 -0800440 if (!populateVarNameMetadata(ExportVarMetadata)) {
441 ALOGE("Could not populate export variable metadata");
442 return false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700443 }
444
Stephen Hines569986d2012-03-09 19:58:45 -0800445 if (!populateFuncNameMetadata(ExportFuncMetadata)) {
446 ALOGE("Could not populate export function metadata");
447 return false;
Stephen Hines932bc6e2011-07-27 16:26:26 -0700448 }
449
Stephen Hinescc366e52012-02-21 17:22:04 -0800450 if (!populateForEachMetadata(ExportForEachNameMetadata,
451 ExportForEachMetadata)) {
Steve Block10c14122012-01-08 10:15:06 +0000452 ALOGE("Could not populate ForEach signature metadata");
Stephen Hines33f8fe22011-08-17 12:56:22 -0700453 return false;
454 }
455
Stephen Hines932bc6e2011-07-27 16:26:26 -0700456 populatePragmaMetadata(PragmaMetadata);
457
458 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
Steve Block10c14122012-01-08 10:15:06 +0000459 ALOGE("Could not populate object slot metadata");
Stephen Hines932bc6e2011-07-27 16:26:26 -0700460 return false;
461 }
462
Stephen Hines932bc6e2011-07-27 16:26:26 -0700463 return true;
464}
465
466} // namespace bcinfo
467