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#ifndef __ANDROID_BCINFO_METADATAEXTRACTOR_H__
18#define __ANDROID_BCINFO_METADATAEXTRACTOR_H__
19
20#include <cstddef>
21#include <memory>
22
23#include <stdint.h>
24
25namespace llvm {
26  class Function;
27  class Module;
28  class NamedMDNode;
29}
30
31namespace bcinfo {
32
33enum RSFloatPrecision {
34  RS_FP_Full = 0,
35  RS_FP_Relaxed = 1,
36};
37
38enum MetadataSignatureBitval {
39  MD_SIG_None        = 0,
40  MD_SIG_In          = 0x000001,
41  MD_SIG_Out         = 0x000002,
42  MD_SIG_Usr         = 0x000004,
43  MD_SIG_X           = 0x000008,
44  MD_SIG_Y           = 0x000010,
45  MD_SIG_Kernel      = 0x000020,
46  MD_SIG_Z           = 0x000040,
47  MD_SIG_Ctxt        = 0x000080,
48};
49
50class MetadataExtractor {
51 public:
52  struct Reduce {
53    // These strings are owned by the Reduce instance, and deleted upon its destruction.
54    // They are assumed to have been allocated by "new []" and hence are deleted by "delete []".
55    const char *mReduceName;
56    const char *mInitializerName;
57    const char *mAccumulatorName;
58    const char *mCombinerName;
59    const char *mOutConverterName;
60    const char *mHalterName;
61
62    uint32_t mSignature;   // of accumulator function
63    uint32_t mInputCount;  // of accumulator function (and of kernel itself)
64    uint32_t mAccumulatorDataSize;  // in bytes
65
66    Reduce() :
67        mReduceName(nullptr),
68        mInitializerName(nullptr), mAccumulatorName(nullptr), mCombinerName(nullptr),
69        mOutConverterName(nullptr), mHalterName(nullptr),
70        mSignature(0), mInputCount(0), mAccumulatorDataSize(0) {
71    }
72    ~Reduce() {
73      delete [] mReduceName;
74      delete [] mInitializerName;
75      delete [] mAccumulatorName;
76      delete [] mCombinerName;
77      delete [] mOutConverterName;
78      delete [] mHalterName;
79    }
80
81    Reduce(const Reduce &) = delete;
82    void operator=(const Reduce &) = delete;
83  };
84
85 private:
86  const llvm::Module *mModule;
87  const char *mBitcode;
88  size_t mBitcodeSize;
89
90  size_t mExportVarCount;
91  size_t mExportFuncCount;
92  size_t mExportForEachSignatureCount;
93  size_t mExportReduceCount;
94  const char **mExportVarNameList;
95  const char **mExportFuncNameList;
96  const char **mExportForEachNameList;
97  const uint32_t *mExportForEachSignatureList;
98  const uint32_t *mExportForEachInputCountList;
99  const Reduce *mExportReduceList;
100
101  size_t mPragmaCount;
102  const char **mPragmaKeyList;
103  const char **mPragmaValueList;
104
105  size_t mObjectSlotCount;
106  const uint32_t *mObjectSlotList;
107
108  uint32_t mTargetAPI;
109  uint32_t mCompilerVersion;
110  uint32_t mOptimizationLevel;
111
112  enum RSFloatPrecision mRSFloatPrecision;
113
114  // Flag to mark that script is threadable.  True by default.
115  bool mIsThreadable;
116
117  const char *mBuildChecksum;
118
119  bool mHasDebugInfo;
120
121  // Helper functions for extraction
122  bool populateForEachMetadata(const llvm::NamedMDNode *Names,
123                               const llvm::NamedMDNode *Signatures);
124  bool populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata);
125  bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
126  void populatePragmaMetadata(const llvm::NamedMDNode *PragmaMetadata);
127  void readThreadableFlag(const llvm::NamedMDNode *ThreadableMetadata);
128  void readBuildChecksumMetadata(const llvm::NamedMDNode *ChecksumMetadata);
129
130  uint32_t calculateNumInputs(const llvm::Function *Function,
131                              uint32_t Signature);
132
133 public:
134  /**
135   * Reads metadata from \p bitcode.
136   *
137   * \param bitcode - input bitcode string.
138   * \param bitcodeSize - length of \p bitcode string (in bytes).
139   */
140  MetadataExtractor(const char *bitcode, size_t bitcodeSize);
141
142  /**
143   * Reads metadata from \p module.
144   *
145   * \param module - input module.
146   */
147  MetadataExtractor(const llvm::Module *module);
148
149  ~MetadataExtractor();
150
151  /**
152   * Extract the actual metadata from the supplied bitcode.
153   *
154   * \return true on success and false if an error occurred.
155   */
156  bool extract();
157
158  /**
159   * \return target API level of this bitcode.
160   *
161   * The target API is used during the SDK compilation to provide proper
162   * visibility of the RenderScript runtime API functions.
163   */
164  uint32_t getTargetAPI() const {
165    return mTargetAPI;
166  }
167
168  /**
169   * \return number of exported global variables (slots) in this script/module.
170   */
171  size_t getExportVarCount() const {
172    return mExportVarCount;
173  }
174
175  /**
176   * \return array of exported variable names.
177   */
178  const char **getExportVarNameList() const {
179    return mExportVarNameList;
180  }
181
182  /**
183   * \return number of exported global functions (slots) in this script/module.
184   */
185  size_t getExportFuncCount() const {
186    return mExportFuncCount;
187  }
188
189  /**
190   * \return array of exported function names.
191   */
192  const char **getExportFuncNameList() const {
193    return mExportFuncNameList;
194  }
195
196  /**
197   * \return number of exported ForEach functions in this script/module.
198   */
199  size_t getExportForEachSignatureCount() const {
200    return mExportForEachSignatureCount;
201  }
202
203  /**
204   * \return array of exported ForEach function signatures.
205   */
206  const uint32_t *getExportForEachSignatureList() const {
207    return mExportForEachSignatureList;
208  }
209
210  /**
211   * \return array of exported ForEach function names.
212   */
213  const char **getExportForEachNameList() const {
214    return mExportForEachNameList;
215  }
216
217  /**
218   * \return array of input parameter counts.
219   */
220  const uint32_t *getExportForEachInputCountList() const {
221    return mExportForEachInputCountList;
222  }
223
224  /**
225   * \return number of exported general reduce kernels (slots) in this script/module.
226   */
227  size_t getExportReduceCount() const {
228    return mExportReduceCount;
229  }
230
231  /**
232   * \return array of exported general reduce kernel descriptions.
233   */
234  const Reduce *getExportReduceList() const {
235    return mExportReduceList;
236  }
237
238  /**
239   * \return number of pragmas contained in pragmaKeyList and pragmaValueList.
240   */
241  size_t getPragmaCount() const {
242    return mPragmaCount;
243  }
244
245  /**
246   * \return pragma keys (the name for the pragma).
247   */
248  const char **getPragmaKeyList() const {
249    return mPragmaKeyList;
250  }
251
252  /**
253   * \return pragma values (contents corresponding to a particular pragma key).
254   */
255  const char **getPragmaValueList() const {
256    return mPragmaValueList;
257  }
258
259  /**
260   * \return number of object slots contained in objectSlotList.
261   */
262  size_t getObjectSlotCount() const {
263    return mObjectSlotCount;
264  }
265
266  /**
267   * \return array of object slot numbers that must be cleaned up by driver
268   *         on script teardown.
269   */
270  const uint32_t *getObjectSlotList() const {
271    return mObjectSlotList;
272  }
273
274  /**
275   * \return compiler version that generated this bitcode.
276   */
277  uint32_t getCompilerVersion() const {
278    return mCompilerVersion;
279  }
280
281  /**
282   * \return compiler optimization level for this bitcode.
283   */
284  uint32_t getOptimizationLevel() const {
285    return mOptimizationLevel;
286  }
287
288  /**
289   * \return minimal floating point precision that the script requires.
290   */
291  enum RSFloatPrecision getRSFloatPrecision() const {
292    return mRSFloatPrecision;
293  }
294
295  /**
296   * \return whether or not this ForEach function signature has an "In"
297   * parameter.
298   *
299   * \param sig - ForEach function signature to check.
300   */
301  static bool hasForEachSignatureIn(uint32_t sig) {
302    return sig & MD_SIG_In;
303  }
304
305  /**
306   * \return whether or not this ForEach function signature has an "Out"
307   * parameter.
308   *
309   * \param sig - ForEach function signature to check.
310   */
311  static bool hasForEachSignatureOut(uint32_t sig) {
312    return sig & MD_SIG_Out;
313  }
314
315  /**
316   * \return whether or not this ForEach function signature has a "UsrData"
317   * parameter.
318   *
319   * \param sig - ForEach function signature to check.
320   */
321  static bool hasForEachSignatureUsrData(uint32_t sig) {
322    return sig & MD_SIG_Usr;
323  }
324
325  /**
326   * \return whether or not this ForEach function signature has an "X"
327   * parameter.
328   *
329   * \param sig - ForEach function signature to check.
330   */
331  static bool hasForEachSignatureX(uint32_t sig) {
332    return sig & MD_SIG_X;
333  }
334
335  /**
336   * \return whether or not this ForEach function signature has a "Y"
337   * parameter.
338   *
339   * \param sig - ForEach function signature to check.
340   */
341  static bool hasForEachSignatureY(uint32_t sig) {
342    return sig & MD_SIG_Y;
343  }
344
345  /**
346   * \return whether or not this ForEach function signature is a
347   * pass-by-value "Kernel".
348   *
349   * \param sig - ForEach function signature to check.
350   */
351  static bool hasForEachSignatureKernel(uint32_t sig) {
352    return sig & MD_SIG_Kernel;
353  }
354
355  /**
356   * \return whether or not this ForEach function signature has a "Z"
357   * parameter.
358   *
359   * \param sig - ForEach function signature to check.
360   */
361  static bool hasForEachSignatureZ(uint32_t sig) {
362    return sig & MD_SIG_Z;
363  }
364
365  /**
366   * \return whether or not this ForEach function signature has a "Ctxt"
367   * parameter.
368   *
369   * \param sig - ForEach function signature to check.
370   */
371  static bool hasForEachSignatureCtxt(uint32_t sig) {
372    return sig & MD_SIG_Ctxt;
373  }
374
375  /**
376   * \return whether "Kernels" in this script can be processed
377   * by multiple threads
378   */
379
380  bool isThreadable() const {
381    return mIsThreadable;
382  }
383
384  /**
385   * \return the build checksum extracted from the LLVM metadata
386   */
387  const char *getBuildChecksum() const {
388    return mBuildChecksum;
389  }
390
391  /**
392   * \return whether the module contains debug metadata
393   */
394  bool hasDebugInfo() const {
395    return mHasDebugInfo;
396  }
397};
398
399}  // namespace bcinfo
400
401#endif  // __ANDROID_BCINFO_METADATAEXTRACTOR_H__
402