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 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    */
getTargetAPI()164   uint32_t getTargetAPI() const {
165     return mTargetAPI;
166   }
167 
168   /**
169    * \return number of exported global variables (slots) in this script/module.
170    */
getExportVarCount()171   size_t getExportVarCount() const {
172     return mExportVarCount;
173   }
174 
175   /**
176    * \return array of exported variable names.
177    */
getExportVarNameList()178   const char **getExportVarNameList() const {
179     return mExportVarNameList;
180   }
181 
182   /**
183    * \return number of exported global functions (slots) in this script/module.
184    */
getExportFuncCount()185   size_t getExportFuncCount() const {
186     return mExportFuncCount;
187   }
188 
189   /**
190    * \return array of exported function names.
191    */
getExportFuncNameList()192   const char **getExportFuncNameList() const {
193     return mExportFuncNameList;
194   }
195 
196   /**
197    * \return number of exported ForEach functions in this script/module.
198    */
getExportForEachSignatureCount()199   size_t getExportForEachSignatureCount() const {
200     return mExportForEachSignatureCount;
201   }
202 
203   /**
204    * \return array of exported ForEach function signatures.
205    */
getExportForEachSignatureList()206   const uint32_t *getExportForEachSignatureList() const {
207     return mExportForEachSignatureList;
208   }
209 
210   /**
211    * \return array of exported ForEach function names.
212    */
getExportForEachNameList()213   const char **getExportForEachNameList() const {
214     return mExportForEachNameList;
215   }
216 
217   /**
218    * \return array of input parameter counts.
219    */
getExportForEachInputCountList()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    */
getExportReduceCount()227   size_t getExportReduceCount() const {
228     return mExportReduceCount;
229   }
230 
231   /**
232    * \return array of exported general reduce kernel descriptions.
233    */
getExportReduceList()234   const Reduce *getExportReduceList() const {
235     return mExportReduceList;
236   }
237 
238   /**
239    * \return number of pragmas contained in pragmaKeyList and pragmaValueList.
240    */
getPragmaCount()241   size_t getPragmaCount() const {
242     return mPragmaCount;
243   }
244 
245   /**
246    * \return pragma keys (the name for the pragma).
247    */
getPragmaKeyList()248   const char **getPragmaKeyList() const {
249     return mPragmaKeyList;
250   }
251 
252   /**
253    * \return pragma values (contents corresponding to a particular pragma key).
254    */
getPragmaValueList()255   const char **getPragmaValueList() const {
256     return mPragmaValueList;
257   }
258 
259   /**
260    * \return number of object slots contained in objectSlotList.
261    */
getObjectSlotCount()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    */
getObjectSlotList()270   const uint32_t *getObjectSlotList() const {
271     return mObjectSlotList;
272   }
273 
274   /**
275    * \return compiler version that generated this bitcode.
276    */
getCompilerVersion()277   uint32_t getCompilerVersion() const {
278     return mCompilerVersion;
279   }
280 
281   /**
282    * \return compiler optimization level for this 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