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#include <cutils/properties.h>
24
25#include "llvm/ADT/OwningPtr.h"
26#include "llvm/Bitcode/ReaderWriter.h"
27#include "llvm/Constants.h"
28#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
48// 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
53// 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
57// 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)
63    : 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),
68      mObjectSlotCount(0), mObjectSlotList(NULL),
69      mRSFloatPrecision(RS_FP_Full) {
70  BitcodeWrapper wrapper(bitcode, bitcodeSize);
71  mCompilerVersion = wrapper.getCompilerVersion();
72  mOptimizationLevel = wrapper.getOptimizationLevel();
73}
74
75
76MetadataExtractor::MetadataExtractor(const llvm::Module *module)
77    : mModule(module), mBitcode(NULL), mBitcodeSize(0), mExportVarCount(0),
78      mExportFuncCount(0), mExportForEachSignatureCount(0),
79      mExportVarNameList(NULL), mExportFuncNameList(NULL),
80      mExportForEachNameList(NULL), mExportForEachSignatureList(NULL),
81      mPragmaCount(0), mPragmaKeyList(NULL), mPragmaValueList(NULL),
82      mObjectSlotCount(0), mObjectSlotList(NULL),
83      mRSFloatPrecision(RS_FP_Full) {
84  mCompilerVersion = 0;
85  mOptimizationLevel = 3;
86}
87
88
89MetadataExtractor::~MetadataExtractor() {
90  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
108  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
117  delete [] mExportForEachSignatureList;
118  mExportForEachSignatureList = NULL;
119
120  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;
128    }
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)) {
166          ALOGE("Non-integer object slot value '%s'", Slot.str().c_str());
167          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
206  const char **TmpKeyList = new const char*[mPragmaCount];
207  const char **TmpValueList = new const char*[mPragmaCount];
208
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);
213      TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
214      llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
215      TmpValueList[i] = createStringFromValue(PragmaValueMDS);
216    }
217  }
218
219  mPragmaKeyList = TmpKeyList;
220  mPragmaValueList = TmpValueList;
221
222  // 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");
225  std::string Full("rs_fp_full");
226  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
251  // 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
271  return;
272}
273
274
275bool 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
327bool MetadataExtractor::populateForEachMetadata(
328    const llvm::NamedMDNode *Names,
329    const llvm::NamedMDNode *Signatures) {
330  if (!Names && !Signatures) {
331    // 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;
335    char **TmpNameList = new char*[mExportForEachSignatureCount];
336    TmpNameList[0] = new char[5];
337    strncpy(TmpNameList[0], "root", 5);
338
339    uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
340    TmpSigList[0] = 0x1f;
341
342    mExportForEachNameList = (const char**)TmpNameList;
343    mExportForEachSignatureList = TmpSigList;
344    return true;
345  }
346
347  if (Signatures) {
348    mExportForEachSignatureCount = Signatures->getNumOperands();
349    if (!mExportForEachSignatureCount) {
350      return true;
351    }
352  } else {
353    mExportForEachSignatureCount = 0;
354    mExportForEachSignatureList = NULL;
355    return true;
356  }
357
358  uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
359  const char **TmpNameList = new const char*[mExportForEachSignatureCount];
360
361  for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
362    llvm::MDNode *SigNode = Signatures->getOperand(i);
363    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)) {
370          ALOGE("Non-integer signature value '%s'", SigString.str().c_str());
371          return false;
372        }
373        TmpSigList[i] = Signature;
374      }
375    }
376  }
377
378  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      }
384    }
385  } else {
386    if (mExportForEachSignatureCount != 1) {
387      ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
388            mExportForEachSignatureCount);
389    }
390    char *RootName = new char[5];
391    strncpy(RootName, "root", 5);
392    TmpNameList[0] = RootName;
393  }
394
395  mExportForEachNameList = TmpNameList;
396  mExportForEachSignatureList = TmpSigList;
397
398  return true;
399}
400
401
402bool MetadataExtractor::extract() {
403  if (!(mBitcode && mBitcodeSize) && !mModule) {
404    ALOGE("Invalid/empty bitcode/module");
405    return false;
406  }
407
408  llvm::OwningPtr<llvm::LLVMContext> mContext;
409
410  if (!mModule) {
411    mContext.reset(new llvm::LLVMContext());
412    llvm::OwningPtr<llvm::MemoryBuffer> MEM(
413      llvm::MemoryBuffer::getMemBuffer(
414        llvm::StringRef(mBitcode, mBitcodeSize), "", false));
415    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    }
424  }
425
426  const llvm::NamedMDNode *ExportVarMetadata =
427      mModule->getNamedMetadata(ExportVarMetadataName);
428  const llvm::NamedMDNode *ExportFuncMetadata =
429      mModule->getNamedMetadata(ExportFuncMetadataName);
430  const llvm::NamedMDNode *ExportForEachNameMetadata =
431      mModule->getNamedMetadata(ExportForEachNameMetadataName);
432  const llvm::NamedMDNode *ExportForEachMetadata =
433      mModule->getNamedMetadata(ExportForEachMetadataName);
434  const llvm::NamedMDNode *PragmaMetadata =
435      mModule->getNamedMetadata(PragmaMetadataName);
436  const llvm::NamedMDNode *ObjectSlotMetadata =
437      mModule->getNamedMetadata(ObjectSlotMetadataName);
438
439
440  if (!populateVarNameMetadata(ExportVarMetadata)) {
441    ALOGE("Could not populate export variable metadata");
442    return false;
443  }
444
445  if (!populateFuncNameMetadata(ExportFuncMetadata)) {
446    ALOGE("Could not populate export function metadata");
447    return false;
448  }
449
450  if (!populateForEachMetadata(ExportForEachNameMetadata,
451                               ExportForEachMetadata)) {
452    ALOGE("Could not populate ForEach signature metadata");
453    return false;
454  }
455
456  populatePragmaMetadata(PragmaMetadata);
457
458  if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
459    ALOGE("Could not populate object slot metadata");
460    return false;
461  }
462
463  return true;
464}
465
466}  // namespace bcinfo
467
468