/*
* Copyright 2011-2012, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __ANDROID_BCINFO_METADATAEXTRACTOR_H__
#define __ANDROID_BCINFO_METADATAEXTRACTOR_H__
#include <cstddef>
#include <memory>
#include <stdint.h>
namespace llvm {
class Function;
class Module;
class NamedMDNode;
}
namespace bcinfo {
enum RSFloatPrecision {
RS_FP_Full = 0,
RS_FP_Relaxed = 1,
};
enum MetadataSignatureBitval {
MD_SIG_None = 0,
MD_SIG_In = 0x000001,
MD_SIG_Out = 0x000002,
MD_SIG_Usr = 0x000004,
MD_SIG_X = 0x000008,
MD_SIG_Y = 0x000010,
MD_SIG_Kernel = 0x000020,
MD_SIG_Z = 0x000040,
MD_SIG_Ctxt = 0x000080,
};
class MetadataExtractor {
public:
struct Reduce {
// These strings are owned by the Reduce instance, and deleted upon its destruction.
// They are assumed to have been allocated by "new []" and hence are deleted by "delete []".
const char *mReduceName;
const char *mInitializerName;
const char *mAccumulatorName;
const char *mCombinerName;
const char *mOutConverterName;
const char *mHalterName;
uint32_t mSignature; // of accumulator function
uint32_t mInputCount; // of accumulator function (and of kernel itself)
uint32_t mAccumulatorDataSize; // in bytes
Reduce() :
mReduceName(nullptr),
mInitializerName(nullptr), mAccumulatorName(nullptr), mCombinerName(nullptr),
mOutConverterName(nullptr), mHalterName(nullptr),
mSignature(0), mInputCount(0), mAccumulatorDataSize(0) {
}
~Reduce() {
delete [] mReduceName;
delete [] mInitializerName;
delete [] mAccumulatorName;
delete [] mCombinerName;
delete [] mOutConverterName;
delete [] mHalterName;
}
Reduce(const Reduce &) = delete;
void operator=(const Reduce &) = delete;
};
private:
const llvm::Module *mModule;
const char *mBitcode;
size_t mBitcodeSize;
size_t mExportVarCount;
size_t mExportFuncCount;
size_t mExportForEachSignatureCount;
size_t mExportReduceCount;
const char **mExportVarNameList;
const char **mExportFuncNameList;
const char **mExportForEachNameList;
const uint32_t *mExportForEachSignatureList;
const uint32_t *mExportForEachInputCountList;
const Reduce *mExportReduceList;
size_t mPragmaCount;
const char **mPragmaKeyList;
const char **mPragmaValueList;
size_t mObjectSlotCount;
const uint32_t *mObjectSlotList;
uint32_t mTargetAPI;
uint32_t mCompilerVersion;
uint32_t mOptimizationLevel;
enum RSFloatPrecision mRSFloatPrecision;
// Flag to mark that script is threadable. True by default.
bool mIsThreadable;
const char *mBuildChecksum;
bool mHasDebugInfo;
// Helper functions for extraction
bool populateForEachMetadata(const llvm::NamedMDNode *Names,
const llvm::NamedMDNode *Signatures);
bool populateReduceMetadata(const llvm::NamedMDNode *ReduceMetadata);
bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
void populatePragmaMetadata(const llvm::NamedMDNode *PragmaMetadata);
void readThreadableFlag(const llvm::NamedMDNode *ThreadableMetadata);
void readBuildChecksumMetadata(const llvm::NamedMDNode *ChecksumMetadata);
uint32_t calculateNumInputs(const llvm::Function *Function,
uint32_t Signature);
public:
/**
* Reads metadata from \p bitcode.
*
* \param bitcode - input bitcode string.
* \param bitcodeSize - length of \p bitcode string (in bytes).
*/
MetadataExtractor(const char *bitcode, size_t bitcodeSize);
/**
* Reads metadata from \p module.
*
* \param module - input module.
*/
MetadataExtractor(const llvm::Module *module);
~MetadataExtractor();
/**
* Extract the actual metadata from the supplied bitcode.
*
* \return true on success and false if an error occurred.
*/
bool extract();
/**
* \return target API level of this bitcode.
*
* The target API is used during the SDK compilation to provide proper
* visibility of the RenderScript runtime API functions.
*/
uint32_t getTargetAPI() const {
return mTargetAPI;
}
/**
* \return number of exported global variables (slots) in this script/module.
*/
size_t getExportVarCount() const {
return mExportVarCount;
}
/**
* \return array of exported variable names.
*/
const char **getExportVarNameList() const {
return mExportVarNameList;
}
/**
* \return number of exported global functions (slots) in this script/module.
*/
size_t getExportFuncCount() const {
return mExportFuncCount;
}
/**
* \return array of exported function names.
*/
const char **getExportFuncNameList() const {
return mExportFuncNameList;
}
/**
* \return number of exported ForEach functions in this script/module.
*/
size_t getExportForEachSignatureCount() const {
return mExportForEachSignatureCount;
}
/**
* \return array of exported ForEach function signatures.
*/
const uint32_t *getExportForEachSignatureList() const {
return mExportForEachSignatureList;
}
/**
* \return array of exported ForEach function names.
*/
const char **getExportForEachNameList() const {
return mExportForEachNameList;
}
/**
* \return array of input parameter counts.
*/
const uint32_t *getExportForEachInputCountList() const {
return mExportForEachInputCountList;
}
/**
* \return number of exported general reduce kernels (slots) in this script/module.
*/
size_t getExportReduceCount() const {
return mExportReduceCount;
}
/**
* \return array of exported general reduce kernel descriptions.
*/
const Reduce *getExportReduceList() const {
return mExportReduceList;
}
/**
* \return number of pragmas contained in pragmaKeyList and pragmaValueList.
*/
size_t getPragmaCount() const {
return mPragmaCount;
}
/**
* \return pragma keys (the name for the pragma).
*/
const char **getPragmaKeyList() const {
return mPragmaKeyList;
}
/**
* \return pragma values (contents corresponding to a particular pragma key).
*/
const char **getPragmaValueList() const {
return mPragmaValueList;
}
/**
* \return number of object slots contained in objectSlotList.
*/
size_t getObjectSlotCount() const {
return mObjectSlotCount;
}
/**
* \return array of object slot numbers that must be cleaned up by driver
* on script teardown.
*/
const uint32_t *getObjectSlotList() const {
return mObjectSlotList;
}
/**
* \return compiler version that generated this bitcode.
*/
uint32_t getCompilerVersion() const {
return mCompilerVersion;
}
/**
* \return compiler optimization level for this bitcode.
*/
uint32_t getOptimizationLevel() const {
return mOptimizationLevel;
}
/**
* \return minimal floating point precision that the script requires.
*/
enum RSFloatPrecision getRSFloatPrecision() const {
return mRSFloatPrecision;
}
/**
* \return whether or not this ForEach function signature has an "In"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureIn(uint32_t sig) {
return sig & MD_SIG_In;
}
/**
* \return whether or not this ForEach function signature has an "Out"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureOut(uint32_t sig) {
return sig & MD_SIG_Out;
}
/**
* \return whether or not this ForEach function signature has a "UsrData"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureUsrData(uint32_t sig) {
return sig & MD_SIG_Usr;
}
/**
* \return whether or not this ForEach function signature has an "X"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureX(uint32_t sig) {
return sig & MD_SIG_X;
}
/**
* \return whether or not this ForEach function signature has a "Y"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureY(uint32_t sig) {
return sig & MD_SIG_Y;
}
/**
* \return whether or not this ForEach function signature is a
* pass-by-value "Kernel".
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureKernel(uint32_t sig) {
return sig & MD_SIG_Kernel;
}
/**
* \return whether or not this ForEach function signature has a "Z"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureZ(uint32_t sig) {
return sig & MD_SIG_Z;
}
/**
* \return whether or not this ForEach function signature has a "Ctxt"
* parameter.
*
* \param sig - ForEach function signature to check.
*/
static bool hasForEachSignatureCtxt(uint32_t sig) {
return sig & MD_SIG_Ctxt;
}
/**
* \return whether "Kernels" in this script can be processed
* by multiple threads
*/
bool isThreadable() const {
return mIsThreadable;
}
/**
* \return the build checksum extracted from the LLVM metadata
*/
const char *getBuildChecksum() const {
return mBuildChecksum;
}
/**
* \return whether the module contains debug metadata
*/
bool hasDebugInfo() const {
return mHasDebugInfo;
}
};
} // namespace bcinfo
#endif // __ANDROID_BCINFO_METADATAEXTRACTOR_H__