| /* |
| * Copyright 2017, 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 MODULE_H |
| #define MODULE_H |
| |
| #include <iostream> |
| #include <map> |
| #include <vector> |
| |
| #include "core_defs.h" |
| #include "entity.h" |
| #include "instructions.h" |
| #include "stl_util.h" |
| #include "types_generated.h" |
| #include "visitor.h" |
| |
| namespace android { |
| namespace spirit { |
| |
| class Builder; |
| class AnnotationSection; |
| class CapabilityInst; |
| class DebugInfoSection; |
| class ExtensionInst; |
| class ExtInstImportInst; |
| class EntryPointInst; |
| class ExecutionModeInst; |
| class EntryPointDefinition; |
| class FunctionDeclaration; |
| class FunctionDefinition; |
| class GlobalSection; |
| class InputWordStream; |
| class Instruction; |
| class MemoryModelInst; |
| |
| union VersionNumber { |
| struct { |
| uint8_t mLowZero; |
| uint8_t mMinorNumber; |
| uint8_t mMajorNumber; |
| uint8_t mHighZero; |
| } mMajorMinor; |
| uint8_t mBytes[4]; |
| uint32_t mWord; |
| }; |
| |
| class Module : public Entity { |
| public: |
| static Module *getCurrentModule(); |
| uint32_t nextId() { return mNextId++; } |
| |
| Module(); |
| |
| Module(Builder *b); |
| |
| virtual ~Module() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void Serialize(OutputWordStream &OS) const override; |
| |
| void SerializeHeader(OutputWordStream &OS) const; |
| |
| void registerId(uint32_t id, Instruction *inst) { |
| mIdTable.insert(std::make_pair(id, inst)); |
| } |
| |
| void initialize(); |
| |
| bool resolveIds(); |
| |
| void accept(IVisitor *v) override { |
| for (auto cap : mCapabilities) { |
| v->visit(cap); |
| } |
| for (auto ext : mExtensions) { |
| v->visit(ext); |
| } |
| for (auto imp : mExtInstImports) { |
| v->visit(imp); |
| } |
| |
| v->visit(mMemoryModel.get()); |
| |
| for (auto entry : mEntryPoints) { |
| v->visit(entry); |
| } |
| |
| for (auto mode : mExecutionModes) { |
| v->visit(mode); |
| } |
| |
| v->visit(mDebugInfo.get()); |
| if (mAnnotations) { |
| v->visit(mAnnotations.get()); |
| } |
| if (mGlobals) { |
| v->visit(mGlobals.get()); |
| } |
| |
| for (auto def : mFunctionDefinitions) { |
| v->visit(def); |
| } |
| } |
| |
| static std::ostream &errs() { return std::cerr; } |
| |
| Module *addCapability(Capability cap); |
| Module *setMemoryModel(AddressingModel am, MemoryModel mm); |
| Module *addExtInstImport(const char *extName); |
| Module *addSource(SourceLanguage lang, int version); |
| Module *addSourceExtension(const char *ext); |
| Module *addString(const char *ext); |
| Module *addEntryPoint(EntryPointDefinition *entry); |
| |
| ExtInstImportInst *getGLExt() const { return mGLExt; } |
| |
| GlobalSection *getGlobalSection(); |
| |
| Instruction *lookupByName(const char *) const; |
| FunctionDefinition * |
| getFunctionDefinitionFromInstruction(FunctionInst *) const; |
| FunctionDefinition *lookupFunctionDefinitionByName(const char *name) const; |
| |
| // Find the name of the instruction, e.g., the name of a function (OpFunction |
| // instruction). |
| // The returned string is owned by the OpName instruction, whose first operand |
| // is the instruction being queried on. |
| const char *lookupNameByInstruction(const Instruction *) const; |
| |
| VariableInst *getInvocationId(); |
| VariableInst *getNumWorkgroups(); |
| |
| // Adds a struct type built somewhere else. |
| Module *addStructType(TypeStructInst *structType); |
| Module *addVariable(VariableInst *var); |
| |
| // Methods to look up types. Create them if not found. |
| TypeVoidInst *getVoidType(); |
| TypeIntInst *getIntType(int bits, bool isSigned = true); |
| TypeIntInst *getUnsignedIntType(int bits); |
| TypeFloatInst *getFloatType(int bits); |
| TypeVectorInst *getVectorType(Instruction *componentType, int width); |
| TypePointerInst *getPointerType(StorageClass storage, |
| Instruction *pointeeType); |
| TypeRuntimeArrayInst *getRuntimeArrayType(Instruction *elementType); |
| |
| // This implies that struct types are strictly structural equivalent, i.e., |
| // two structs are equivalent i.f.f. their fields are equivalent, recursively. |
| TypeStructInst *getStructType(Instruction *fieldType[], int numField); |
| TypeStructInst *getStructType(const std::vector<Instruction *> &fieldType); |
| TypeStructInst *getStructType(Instruction *field0Type); |
| TypeStructInst *getStructType(Instruction *field0Type, |
| Instruction *field1Type); |
| TypeStructInst *getStructType(Instruction *field0Type, |
| Instruction *field1Type, |
| Instruction *field2Type); |
| |
| // TODO: Can function types of different decorations be considered the same? |
| TypeFunctionInst *getFunctionType(Instruction *retType, |
| Instruction *const argType[], |
| size_t numArg); |
| TypeFunctionInst *getFunctionType(Instruction *retType, |
| const std::vector<Instruction *> &argTypes); |
| |
| size_t getSize(TypeVoidInst *voidTy); |
| size_t getSize(TypeIntInst *intTy); |
| size_t getSize(TypeFloatInst *fpTy); |
| size_t getSize(TypeVectorInst *vTy); |
| size_t getSize(TypePointerInst *ptrTy); |
| size_t getSize(TypeStructInst *structTy); |
| size_t getSize(TypeFunctionInst *funcTy); |
| size_t getSize(Instruction *inst); |
| |
| ConstantInst *getConstant(TypeIntInst *type, int32_t value); |
| ConstantInst *getConstant(TypeIntInst *type, uint32_t value); |
| ConstantInst *getConstant(TypeFloatInst *type, float value); |
| |
| ConstantCompositeInst *getConstantComposite(TypeVectorInst *type, |
| ConstantInst *components[], |
| size_t width); |
| ConstantCompositeInst * |
| getConstantComposite(Instruction *type, |
| const std::vector<ConstantInst *> &components); |
| ConstantCompositeInst *getConstantComposite(Instruction *type, |
| ConstantInst *comp0, |
| ConstantInst *comp1); |
| ConstantCompositeInst *getConstantComposite(TypeVectorInst *type, |
| ConstantInst *comp0, |
| ConstantInst *comp1, |
| ConstantInst *comp2); |
| ConstantCompositeInst *getConstantComposite(TypeVectorInst *type, |
| ConstantInst *comp0, |
| ConstantInst *comp1, |
| ConstantInst *comp2, |
| ConstantInst *comp3); |
| |
| Module *addFunctionDefinition(FunctionDefinition *func); |
| |
| void consolidateAnnotations(); |
| |
| private: |
| static Module *mInstance; |
| uint32_t mNextId; |
| std::map<uint32_t, Instruction *> mIdTable; |
| |
| uint32_t mMagicNumber; |
| VersionNumber mVersion; |
| uint32_t mGeneratorMagicNumber; |
| uint32_t mBound; |
| uint32_t mReserved; |
| |
| std::vector<CapabilityInst *> mCapabilities; |
| std::vector<ExtensionInst *> mExtensions; |
| std::vector<ExtInstImportInst *> mExtInstImports; |
| std::unique_ptr<MemoryModelInst> mMemoryModel; |
| std::vector<EntryPointInst *> mEntryPointInsts; |
| std::vector<ExecutionModeInst *> mExecutionModes; |
| std::vector<EntryPointDefinition *> mEntryPoints; |
| std::unique_ptr<DebugInfoSection> mDebugInfo; |
| std::unique_ptr<AnnotationSection> mAnnotations; |
| std::unique_ptr<GlobalSection> mGlobals; |
| std::vector<FunctionDefinition *> mFunctionDefinitions; |
| |
| ExtInstImportInst *mGLExt; |
| |
| ContainerDeleter<std::vector<CapabilityInst *>> mCapabilitiesDeleter; |
| ContainerDeleter<std::vector<ExtensionInst *>> mExtensionsDeleter; |
| ContainerDeleter<std::vector<ExtInstImportInst *>> mExtInstImportsDeleter; |
| ContainerDeleter<std::vector<EntryPointInst *>> mEntryPointInstsDeleter; |
| ContainerDeleter<std::vector<ExecutionModeInst *>> mExecutionModesDeleter; |
| ContainerDeleter<std::vector<EntryPointDefinition *>> mEntryPointsDeleter; |
| ContainerDeleter<std::vector<FunctionDefinition *>> |
| mFunctionDefinitionsDeleter; |
| }; |
| |
| struct Extent3D { |
| uint32_t mWidth; |
| uint32_t mHeight; |
| uint32_t mDepth; |
| }; |
| |
| class EntryPointDefinition : public Entity { |
| public: |
| EntryPointDefinition() {} |
| EntryPointDefinition(Builder *builder, ExecutionModel execModel, |
| FunctionDefinition *func, const char *name); |
| |
| virtual ~EntryPointDefinition() { |
| // Nothing to do here since ~Module() will delete entities referenced here |
| } |
| |
| void accept(IVisitor *visitor) override { |
| visitor->visit(mEntryPointInst); |
| // Do not visit the ExecutionMode instructions here. They are linked here |
| // for convinience, and for convinience only. They are all grouped, stored, |
| // and serialized directly in the module in a section right after all |
| // EntryPoint instructions. Visit them from there. |
| } |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| EntryPointDefinition *addToInterface(VariableInst *var); |
| EntryPointDefinition *addExecutionMode(ExecutionModeInst *mode) { |
| mExecutionModeInsts.push_back(mode); |
| return this; |
| } |
| const std::vector<ExecutionModeInst *> &getExecutionModes() const { |
| return mExecutionModeInsts; |
| } |
| |
| EntryPointDefinition *setLocalSize(uint32_t width, uint32_t height, |
| uint32_t depth); |
| |
| EntryPointDefinition *applyExecutionMode(ExecutionModeInst *mode); |
| |
| EntryPointInst *getInstruction() const { return mEntryPointInst; } |
| |
| private: |
| const char *mName; |
| FunctionInst *mFunction; |
| ExecutionModel mExecutionModel; |
| std::vector<VariableInst *> mInterface; |
| Extent3D mLocalSize; |
| |
| EntryPointInst *mEntryPointInst; |
| std::vector<ExecutionModeInst *> mExecutionModeInsts; |
| }; |
| |
| class DebugInfoSection : public Entity { |
| public: |
| DebugInfoSection() : mSourcesDeleter(mSources), mNamesDeleter(mNames) {} |
| DebugInfoSection(Builder *b) |
| : Entity(b), mSourcesDeleter(mSources), mNamesDeleter(mNames) {} |
| |
| virtual ~DebugInfoSection() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| DebugInfoSection *addSource(SourceLanguage lang, int version); |
| DebugInfoSection *addSourceExtension(const char *ext); |
| DebugInfoSection *addString(const char *str); |
| |
| Instruction *lookupByName(const char *name) const; |
| const char *lookupNameByInstruction(const Instruction *) const; |
| |
| void accept(IVisitor *v) override { |
| for (auto source : mSources) { |
| v->visit(source); |
| } |
| for (auto name : mNames) { |
| v->visit(name); |
| } |
| } |
| |
| private: |
| // (OpString|OpSource|OpSourceExtension|OpSourceContinued)* |
| std::vector<Instruction *> mSources; |
| // (OpName|OpMemberName)* |
| std::vector<Instruction *> mNames; |
| |
| ContainerDeleter<std::vector<Instruction *>> mSourcesDeleter; |
| ContainerDeleter<std::vector<Instruction *>> mNamesDeleter; |
| }; |
| |
| class AnnotationSection : public Entity { |
| public: |
| AnnotationSection(); |
| AnnotationSection(Builder *b); |
| |
| virtual ~AnnotationSection() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void accept(IVisitor *v) override { |
| for (auto inst : mAnnotations) { |
| v->visit(inst); |
| } |
| } |
| |
| template <typename T> void addAnnotations(T begin, T end) { |
| mAnnotations.insert<T>(std::end(mAnnotations), begin, end); |
| } |
| |
| std::vector<Instruction *>::const_iterator begin() const { |
| return mAnnotations.begin(); |
| } |
| |
| std::vector<Instruction *>::const_iterator end() const { |
| return mAnnotations.end(); |
| } |
| |
| void clear() { mAnnotations.clear(); } |
| |
| private: |
| std::vector<Instruction *> mAnnotations; // OpDecorate, etc. |
| |
| ContainerDeleter<std::vector<Instruction *>> mAnnotationsDeleter; |
| }; |
| |
| // Types, constants, and globals |
| class GlobalSection : public Entity { |
| public: |
| GlobalSection(); |
| GlobalSection(Builder *builder); |
| |
| virtual ~GlobalSection() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void accept(IVisitor *v) override { |
| for (auto inst : mGlobalDefs) { |
| v->visit(inst); |
| } |
| |
| if (mInvocationId) { |
| v->visit(mInvocationId.get()); |
| } |
| |
| if (mNumWorkgroups) { |
| v->visit(mNumWorkgroups.get()); |
| } |
| } |
| |
| ConstantInst *getConstant(TypeIntInst *type, int32_t value); |
| ConstantInst *getConstant(TypeIntInst *type, uint32_t value); |
| ConstantInst *getConstant(TypeFloatInst *type, float value); |
| ConstantCompositeInst *getConstantComposite(TypeVectorInst *type, |
| ConstantInst *components[], |
| size_t width); |
| |
| // Methods to look up types. Create them if not found. |
| TypeVoidInst *getVoidType(); |
| TypeIntInst *getIntType(int bits, bool isSigned = true); |
| TypeFloatInst *getFloatType(int bits); |
| TypeVectorInst *getVectorType(Instruction *componentType, int width); |
| TypePointerInst *getPointerType(StorageClass storage, |
| Instruction *pointeeType); |
| TypeRuntimeArrayInst *getRuntimeArrayType(Instruction *elementType); |
| |
| // This implies that struct types are strictly structural equivalent, i.e., |
| // two structs are equivalent i.f.f. their fields are equivalent, recursively. |
| TypeStructInst *getStructType(Instruction *fieldType[], int numField); |
| // TypeStructInst *getStructType(const std::vector<Instruction *> |
| // &fieldTypes); |
| |
| // TODO: Can function types of different decorations be considered the same? |
| TypeFunctionInst *getFunctionType(Instruction *retType, |
| Instruction *const argType[], |
| size_t numArg); |
| // TypeStructInst *addStructType(Instruction *fieldType[], int numField); |
| GlobalSection *addStructType(TypeStructInst *structType); |
| GlobalSection *addVariable(VariableInst *var); |
| |
| VariableInst *getInvocationId(); |
| VariableInst *getNumWorkgroups(); |
| |
| private: |
| // TODO: Add structure to this. |
| // Separate types, constants, variables, etc. |
| std::vector<Instruction *> mGlobalDefs; |
| std::unique_ptr<VariableInst> mInvocationId; |
| std::unique_ptr<VariableInst> mNumWorkgroups; |
| |
| ContainerDeleter<std::vector<Instruction *>> mGlobalDefsDeleter; |
| }; |
| |
| class FunctionDeclaration : public Entity { |
| public: |
| virtual ~FunctionDeclaration() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void accept(IVisitor *v) override { |
| v->visit(mFunc); |
| for (auto param : mParams) { |
| v->visit(param); |
| } |
| v->visit(mFuncEnd); |
| } |
| |
| private: |
| FunctionInst *mFunc; |
| std::vector<FunctionParameterInst *> mParams; |
| FunctionEndInst *mFuncEnd; |
| }; |
| |
| class Block : public Entity { |
| public: |
| Block() {} |
| Block(Builder *b) : Entity(b) {} |
| |
| virtual ~Block() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void accept(IVisitor *v) override { |
| for (auto inst : mInsts) { |
| v->visit(inst); |
| } |
| } |
| |
| Block *addInstruction(Instruction *inst) { |
| mInsts.push_back(inst); |
| return this; |
| } |
| |
| private: |
| std::vector<Instruction *> mInsts; |
| }; |
| |
| class FunctionDefinition : public Entity { |
| public: |
| FunctionDefinition(); |
| FunctionDefinition(Builder *builder, FunctionInst *func, |
| FunctionEndInst *end); |
| |
| virtual ~FunctionDefinition() {} |
| |
| bool DeserializeInternal(InputWordStream &IS) override; |
| |
| void accept(IVisitor *v) override { |
| v->visit(mFunc.get()); |
| for (auto param : mParams) { |
| v->visit(param); |
| } |
| for (auto block : mBlocks) { |
| v->visit(block); |
| } |
| v->visit(mFuncEnd.get()); |
| } |
| |
| FunctionDefinition *addBlock(Block *b) { |
| mBlocks.push_back(b); |
| return this; |
| } |
| |
| FunctionInst *getInstruction() const { return mFunc.get(); } |
| FunctionParameterInst *getParameter(uint32_t i) const { return mParams[i]; } |
| |
| Instruction *getReturnType() const; |
| |
| private: |
| std::unique_ptr<FunctionInst> mFunc; |
| std::vector<FunctionParameterInst *> mParams; |
| std::vector<Block *> mBlocks; |
| std::unique_ptr<FunctionEndInst> mFuncEnd; |
| |
| ContainerDeleter<std::vector<FunctionParameterInst *>> mParamsDeleter; |
| ContainerDeleter<std::vector<Block *>> mBlocksDeleter; |
| }; |
| |
| } // namespace spirit |
| } // namespace android |
| |
| #endif // MODULE_H |