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 
25 namespace llvm {
26   class Function;
27   class Module;
28   class NamedMDNode;
29 }
30 
31 namespace bcinfo {
32 
33 enum RSFloatPrecision {
34   RS_FP_Full = 0,
35   RS_FP_Relaxed = 1,
36 };
37 
38 enum 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 
50 class 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 
ReduceReduce66     Reduce() :
67         mReduceName(nullptr),
68         mInitializerName(nullptr), mAccumulatorName(nullptr), mCombinerName(nullptr),
69         mOutConverterName(nullptr), mHalterName(nullptr),
70         mSignature(0), mInputCount(0), mAccumulatorDataSize(0) {
71     }
~ReduceReduce72     ~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 mCompilerVersion;
109   uint32_t mOptimizationLevel;
110 
111   enum RSFloatPrecision mRSFloatPrecision;
112 
113   // Flag to mark that script is threadable.  True by default.
114   bool mIsThreadable;
115 
116   const char *mBuildChecksum;
117 
118   bool mHasDebugInfo;
119 
120   // Helper functions for extraction
121   bool populateForEachMetadata(const llvm::NamedMDNode *Names,
122                                const llvm::NamedMDNode *Signatures);
123   bool populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata);
124   bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
125   void populatePragmaMetadata(const llvm::NamedMDNode *PragmaMetadata);
126   void readThreadableFlag(const llvm::NamedMDNode *ThreadableMetadata);
127   void readBuildChecksumMetadata(const llvm::NamedMDNode *ChecksumMetadata);
128 
129   uint32_t calculateNumInputs(const llvm::Function *Function,
130                               uint32_t Signature);
131 
132  public:
133 
134   // Name of metadata node where information extracted from the
135   // bitcode wrapper should have been stored when we use the
136   // MetadataExtractor constructor that takes a Module as a parameter.
137   static const char kWrapperMetadataName[];
138 
139   /**
140    * Reads metadata from \p bitcode.
141    *
142    * \param bitcode - input bitcode string.
143    * \param bitcodeSize - length of \p bitcode string (in bytes).
144    */
145   MetadataExtractor(const char *bitcode, size_t bitcodeSize);
146 
147   /**
148    * Reads metadata from \p module.
149    *
150    * \param module - input module.
151    *
152    * module must contain a metadata node named kWrapperMetadataName.
153    */
154   explicit MetadataExtractor(const llvm::Module *module);
155 
156   ~MetadataExtractor();
157 
158   /**
159    * Extract the actual metadata from the supplied bitcode.
160    *
161    * \return true on success and false if an error occurred.
162    */
163   bool extract();
164 
165   /**
166    * \return number of exported global variables (slots) in this script/module.
167    */
getExportVarCount()168   size_t getExportVarCount() const {
169     return mExportVarCount;
170   }
171 
172   /**
173    * \return array of exported variable names.
174    */
getExportVarNameList()175   const char **getExportVarNameList() const {
176     return mExportVarNameList;
177   }
178 
179   /**
180    * \return number of exported global functions (slots) in this script/module.
181    */
getExportFuncCount()182   size_t getExportFuncCount() const {
183     return mExportFuncCount;
184   }
185 
186   /**
187    * \return array of exported function names.
188    */
getExportFuncNameList()189   const char **getExportFuncNameList() const {
190     return mExportFuncNameList;
191   }
192 
193   /**
194    * \return number of exported ForEach functions in this script/module.
195    */
getExportForEachSignatureCount()196   size_t getExportForEachSignatureCount() const {
197     return mExportForEachSignatureCount;
198   }
199 
200   /**
201    * \return array of exported ForEach function signatures.
202    */
getExportForEachSignatureList()203   const uint32_t *getExportForEachSignatureList() const {
204     return mExportForEachSignatureList;
205   }
206 
207   /**
208    * \return array of exported ForEach function names.
209    */
getExportForEachNameList()210   const char **getExportForEachNameList() const {
211     return mExportForEachNameList;
212   }
213 
214   /**
215    * \return array of input parameter counts.
216    */
getExportForEachInputCountList()217   const uint32_t *getExportForEachInputCountList() const {
218     return mExportForEachInputCountList;
219   }
220 
221   /**
222    * \return number of exported general reduce kernels (slots) in this script/module.
223    */
getExportReduceCount()224   size_t getExportReduceCount() const {
225     return mExportReduceCount;
226   }
227 
228   /**
229    * \return array of exported general reduce kernel descriptions.
230    */
getExportReduceList()231   const Reduce *getExportReduceList() const {
232     return mExportReduceList;
233   }
234 
235   /**
236    * \return number of pragmas contained in pragmaKeyList and pragmaValueList.
237    */
getPragmaCount()238   size_t getPragmaCount() const {
239     return mPragmaCount;
240   }
241 
242   /**
243    * \return pragma keys (the name for the pragma).
244    */
getPragmaKeyList()245   const char **getPragmaKeyList() const {
246     return mPragmaKeyList;
247   }
248 
249   /**
250    * \return pragma values (contents corresponding to a particular pragma key).
251    */
getPragmaValueList()252   const char **getPragmaValueList() const {
253     return mPragmaValueList;
254   }
255 
256   /**
257    * \return number of object slots contained in objectSlotList.
258    */
getObjectSlotCount()259   size_t getObjectSlotCount() const {
260     return mObjectSlotCount;
261   }
262 
263   /**
264    * \return array of object slot numbers that must be cleaned up by driver
265    *         on script teardown.
266    */
getObjectSlotList()267   const uint32_t *getObjectSlotList() const {
268     return mObjectSlotList;
269   }
270 
271   /**
272    * \return compiler version indicating which guarantees this bitcode is
273    *         known to obey.
274    */
getCompilerVersion()275   uint32_t getCompilerVersion() const {
276     return mCompilerVersion;
277   }
278 
279   /**
280    * \return compiler optimization level for this bitcode.  In the case of
281    *         linked bitcode (user_bitcode + libclcore_bitcode), this is the
282    *         optimization level of user_bitcode.
283    */
getOptimizationLevel()284   uint32_t getOptimizationLevel() const {
285     return mOptimizationLevel;
286   }
287 
288   /**
289    * \return minimal floating point precision that the script requires.
290    */
getRSFloatPrecision()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    */
hasForEachSignatureIn(uint32_t sig)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    */
hasForEachSignatureOut(uint32_t sig)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    */
hasForEachSignatureUsrData(uint32_t sig)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    */
hasForEachSignatureX(uint32_t sig)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    */
hasForEachSignatureY(uint32_t sig)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    */
hasForEachSignatureKernel(uint32_t sig)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    */
hasForEachSignatureZ(uint32_t sig)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    */
hasForEachSignatureCtxt(uint32_t sig)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 
isThreadable()380   bool isThreadable() const {
381     return mIsThreadable;
382   }
383 
384   /**
385    * \return the build checksum extracted from the LLVM metadata
386    */
getBuildChecksum()387   const char *getBuildChecksum() const {
388     return mBuildChecksum;
389   }
390 
391   /**
392    * \return whether the module contains debug metadata
393    */
hasDebugInfo()394   bool hasDebugInfo() const {
395     return mHasDebugInfo;
396   }
397 };
398 
399 }  // namespace bcinfo
400 
401 #endif  // __ANDROID_BCINFO_METADATAEXTRACTOR_H__
402