769 lines
26 KiB
C++
769 lines
26 KiB
C++
//===- SPIRVEntry.h - Base Class for SPIR-V Entities -------------*- C++ -*-===//
|
|
//
|
|
// The LLVM/SPIRV Translator
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
// Copyright (c) 2014 Advanced Micro Devices, Inc. All rights reserved.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
// to deal with the Software without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
//
|
|
// Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimers.
|
|
// Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimers in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
// Neither the names of Advanced Micro Devices, Inc., nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// Software without specific prior written permission.
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
|
|
// THE SOFTWARE.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
///
|
|
/// This file defines the base class for SPIRV entities.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SPIRVENTRY_HPP_
|
|
#define SPIRVENTRY_HPP_
|
|
|
|
#include "SPIRVEnum.h"
|
|
#include "SPIRVIsValidEnum.h"
|
|
#include "SPIRVError.h"
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace SPIRV{
|
|
|
|
class SPIRVModule;
|
|
class SPIRVEncoder;
|
|
class SPIRVDecoder;
|
|
class SPIRVType;
|
|
class SPIRVValue;
|
|
class SPIRVDecorate;
|
|
class SPIRVForward;
|
|
class SPIRVMemberDecorate;
|
|
class SPIRVLine;
|
|
class SPIRVString;
|
|
class SPIRVExtInst;
|
|
|
|
// Add declaration of encode/decode functions to a class.
|
|
// Used inside class definition.
|
|
#define _SPIRV_DCL_ENCDEC \
|
|
void encode(spv_ostream &O) const; \
|
|
void decode(std::istream &I);
|
|
|
|
#define _REQ_SPIRV_VER(Version) \
|
|
SPIRVWord getRequiredSPIRVVersion() const override { return Version; }
|
|
|
|
// Add implementation of encode/decode functions to a class.
|
|
// Used out side of class definition.
|
|
#define _SPIRV_IMP_ENCDEC0(Ty) \
|
|
void Ty::encode(spv_ostream &O) const {} \
|
|
void Ty::decode(std::istream &I) {}
|
|
#define _SPIRV_IMP_ENCDEC1(Ty,x) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x;}
|
|
#define _SPIRV_IMP_ENCDEC2(Ty,x,y) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y;}
|
|
#define _SPIRV_IMP_ENCDEC3(Ty,x,y,z) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
|
|
#define _SPIRV_IMP_ENCDEC4(Ty,x,y,z,u) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
|
|
#define _SPIRV_IMP_ENCDEC5(Ty,x,y,z,u,v) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u << v; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
|
|
#define _SPIRV_IMP_ENCDEC6(Ty,x,y,z,u,v,w) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u << v << w; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
|
|
v >> w;}
|
|
#define _SPIRV_IMP_ENCDEC7(Ty,x,y,z,u,v,w,r) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u << v << w << r; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
|
|
v >> w >> r;}
|
|
#define _SPIRV_IMP_ENCDEC8(Ty,x,y,z,u,v,w,r,s) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u << v << w << r << s; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
|
|
v >> w >> r >> s;}
|
|
#define _SPIRV_IMP_ENCDEC9(Ty,x,y,z,u,v,w,r,s,t) \
|
|
void Ty::encode(spv_ostream &O) const { getEncoder(O) << x << y << z << \
|
|
u << v << w << r << s << t; } \
|
|
void Ty::decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> \
|
|
v >> w >> r >> s >> t;}
|
|
|
|
// Add definition of encode/decode functions to a class.
|
|
// Used inside class definition.
|
|
#define _SPIRV_DEF_ENCDEC0 \
|
|
void encode(spv_ostream &O) const {} \
|
|
void decode(std::istream &I) {}
|
|
#define _SPIRV_DEF_ENCDEC1(x) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x;}
|
|
#define _SPIRV_DEF_ENCDEC2(x,y) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y;}
|
|
#define _SPIRV_DEF_ENCDEC3(x,y,z) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z;}
|
|
#define _SPIRV_DEF_ENCDEC4(x,y,z,u) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u;}
|
|
#define _SPIRV_DEF_ENCDEC5(x,y,z,u,v) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
|
|
v; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v;}
|
|
#define _SPIRV_DEF_ENCDEC6(x,y,z,u,v,w) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
|
|
v << w; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> w;}
|
|
#define _SPIRV_DEF_ENCDEC7(x,y,z,u,v,w,r) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
|
|
v << w << r; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
|
|
w >> r;}
|
|
#define _SPIRV_DEF_ENCDEC8(x,y,z,u,v,w,r,s) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
|
|
v << w << r << s; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
|
|
w >> r >> s;}
|
|
#define _SPIRV_DEF_ENCDEC9(x,y,z,u,v,w,r,s,t) \
|
|
void encode(spv_ostream &O) const { getEncoder(O) << x << y << z << u << \
|
|
v << w << r << s << t; } \
|
|
void decode(std::istream &I) { getDecoder(I) >> x >> y >> z >> u >> v >> \
|
|
w >> r >> s >> t;}
|
|
|
|
/// All SPIR-V in-memory-representation entities inherits from SPIRVEntry.
|
|
/// Usually there are two flavors of constructors of SPIRV objects:
|
|
///
|
|
/// 1. complete constructor: It requires all the parameters needed to create a
|
|
/// SPIRV entity with complete information which can be validated. It is
|
|
/// usually used by LLVM/SPIR-V translator to create SPIRV object
|
|
/// corresponding to LLVM object. Such constructor calls validate() at
|
|
/// the end of the construction.
|
|
///
|
|
/// 2. incomplete constructor: For leaf classes, it has no parameters.
|
|
/// It is usually called by SPIRVEntry::make(opcode) to create an incomplete
|
|
/// object which should not be validated. Then setWordCount(count) is
|
|
/// called to fix the size of the object if it is variable, and then the
|
|
/// information is filled by the virtual function decode(istream).
|
|
/// After that the object can be validated.
|
|
///
|
|
/// To add a new SPIRV class:
|
|
///
|
|
/// 1. It is recommended to name the class as SPIRVXXX if it has a fixed op code
|
|
/// OpXXX. Although it is not mandatory, doing this facilitates adding it to
|
|
/// the table of the factory function SPIRVEntry::create().
|
|
/// 2. Inherit from proper SPIRV class such as SPIRVType, SPIRVValue,
|
|
/// SPIRVInstruction, etc.
|
|
/// 3. Implement virtual function encode(), decode(), validate().
|
|
/// 4. If the object has variable size, implement virtual function
|
|
/// setWordCount().
|
|
/// 5. If the class has special attributes, e.g. having no id, or having no
|
|
/// type as a value, set them in the constructors.
|
|
/// 6. If the class may represent SPIRV entity which has been added in version
|
|
/// later than 1.0, implement virtual function getRequiredSPIRVVersion().
|
|
/// To automaticly update module's version you can also call protected
|
|
/// function updateModuleVersion() in the constructor.
|
|
/// 7. Add the class to the Table of SPIRVEntry::create().
|
|
/// 8. Add the class to SPIRVToLLVM and LLVMToSPIRV.
|
|
|
|
class SPIRVEntry {
|
|
public:
|
|
enum SPIRVEntryAttrib {
|
|
SPIRVEA_DEFAULT = 0,
|
|
SPIRVEA_NOID = 1, // Entry has no valid id
|
|
SPIRVEA_NOTYPE = 2, // Value has no type
|
|
};
|
|
|
|
// Complete constructor for objects with id
|
|
SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
|
|
SPIRVId TheId)
|
|
:Module(M), OpCode(TheOpCode), Id(TheId), Attrib(SPIRVEA_DEFAULT),
|
|
WordCount(TheWordCount), Line(nullptr){
|
|
validate();
|
|
}
|
|
|
|
// Complete constructor for objects without id
|
|
SPIRVEntry(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode)
|
|
:Module(M), OpCode(TheOpCode), Id(SPIRVID_INVALID), Attrib(SPIRVEA_NOID),
|
|
WordCount(TheWordCount), Line(nullptr){
|
|
validate();
|
|
}
|
|
|
|
// Incomplete constructor
|
|
SPIRVEntry(Op TheOpCode)
|
|
:Module(NULL), OpCode(TheOpCode), Id(SPIRVID_INVALID),
|
|
Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
|
|
|
|
SPIRVEntry()
|
|
:Module(NULL), OpCode(OpNop), Id(SPIRVID_INVALID),
|
|
Attrib(SPIRVEA_DEFAULT), WordCount(0), Line(nullptr){}
|
|
|
|
|
|
virtual ~SPIRVEntry(){}
|
|
|
|
bool exist(SPIRVId)const;
|
|
template<class T>
|
|
T* get(SPIRVId TheId)const { return static_cast<T*>(getEntry(TheId));}
|
|
SPIRVEntry *getEntry(SPIRVId) const;
|
|
SPIRVEntry *getOrCreate(SPIRVId TheId) const;
|
|
SPIRVValue *getValue(SPIRVId TheId)const;
|
|
std::vector<SPIRVValue *> getValues(const std::vector<SPIRVId>&)const;
|
|
std::vector<SPIRVId> getIds(const std::vector<SPIRVValue *>)const;
|
|
SPIRVType *getValueType(SPIRVId TheId)const;
|
|
std::vector<SPIRVType *> getValueTypes(const std::vector<SPIRVId>&)const;
|
|
|
|
virtual SPIRVDecoder getDecoder(std::istream &);
|
|
virtual SPIRVEncoder getEncoder(spv_ostream &)const;
|
|
SPIRVErrorLog &getErrorLog()const;
|
|
SPIRVId getId() const { assert(hasId()); return Id;}
|
|
SPIRVLine *getLine() const { return Line;}
|
|
SPIRVLinkageTypeKind getLinkageType() const;
|
|
Op getOpCode() const { return OpCode;}
|
|
SPIRVModule *getModule() const { return Module;}
|
|
virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec();}
|
|
const std::string& getName() const { return Name;}
|
|
bool hasDecorate(Decoration Kind, size_t Index = 0,
|
|
SPIRVWord *Result=0)const;
|
|
std::set<SPIRVWord> getDecorate(Decoration Kind, size_t Index = 0)const;
|
|
bool hasId() const { return !(Attrib & SPIRVEA_NOID);}
|
|
bool hasLine() const { return Line != nullptr;}
|
|
bool hasLinkageType() const;
|
|
bool isAtomic() const { return isAtomicOpCode(OpCode);}
|
|
bool isBasicBlock() const { return isLabel();}
|
|
bool isBuiltinCall() const { return OpCode == OpExtInst;}
|
|
bool isDecorate()const { return OpCode == OpDecorate;}
|
|
bool isMemberDecorate()const { return OpCode == OpMemberDecorate;}
|
|
bool isForward() const { return OpCode == OpForward;}
|
|
bool isLabel() const { return OpCode == OpLabel;}
|
|
bool isUndef() const { return OpCode == OpUndef;}
|
|
bool isControlBarrier() const { return OpCode == OpControlBarrier;}
|
|
bool isMemoryBarrier() const { return OpCode == OpMemoryBarrier;}
|
|
bool isVariable() const { return OpCode == OpVariable;}
|
|
virtual bool isInst() const { return false;}
|
|
virtual bool isOperandLiteral(unsigned Index) const {
|
|
assert(0 && "not implemented");
|
|
return false;
|
|
}
|
|
|
|
void addDecorate(const SPIRVDecorate *);
|
|
void addDecorate(Decoration Kind);
|
|
void addDecorate(Decoration Kind, SPIRVWord Literal);
|
|
void eraseDecorate(Decoration);
|
|
void addMemberDecorate(const SPIRVMemberDecorate *);
|
|
void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
|
|
void addMemberDecorate(SPIRVWord MemberNumber, Decoration Kind,
|
|
SPIRVWord Literal);
|
|
void eraseMemberDecorate(SPIRVWord MemberNumber, Decoration Kind);
|
|
void setHasNoId() { Attrib |= SPIRVEA_NOID;}
|
|
void setId(SPIRVId TheId) { Id = TheId;}
|
|
void setLine(SPIRVLine*);
|
|
void setLinkageType(SPIRVLinkageTypeKind);
|
|
void setModule(SPIRVModule *TheModule);
|
|
void setName(const std::string& TheName);
|
|
virtual void setScope(SPIRVEntry *Scope){};
|
|
void takeAnnotations(SPIRVForward *);
|
|
void takeDecorates(SPIRVEntry *);
|
|
void takeMemberDecorates(SPIRVEntry *);
|
|
void takeLine(SPIRVEntry *);
|
|
|
|
/// After a SPIRV entry is created during reading SPIRV binary by default
|
|
/// constructor, this function is called to allow the SPIRV entry to resize
|
|
/// its variable sized member before decoding the remaining words.
|
|
virtual void setWordCount(SPIRVWord TheWordCount);
|
|
|
|
/// Create an empty SPIRV object by op code, e.g. OpTypeInt creates
|
|
/// SPIRVTypeInt.
|
|
static SPIRVEntry *create(Op);
|
|
static std::unique_ptr<SPIRVEntry> create_unique(Op);
|
|
|
|
/// Create an empty extended instruction.
|
|
static std::unique_ptr<SPIRVExtInst> create_unique(
|
|
SPIRVExtInstSetKind Set,
|
|
unsigned ExtOp);
|
|
|
|
friend spv_ostream &operator<<(spv_ostream &O, const SPIRVEntry &E);
|
|
friend std::istream &operator>>(std::istream &I, SPIRVEntry &E);
|
|
virtual void encodeAll(spv_ostream &O) const;
|
|
virtual void encodeName(spv_ostream &O) const;
|
|
virtual void encodeChildren(spv_ostream &O)const;
|
|
virtual void encodeDecorate(spv_ostream &O)const;
|
|
virtual void encodeWordCountOpCode(spv_ostream &O)const;
|
|
virtual void encode(spv_ostream &O) const;
|
|
virtual void decode(std::istream &I);
|
|
|
|
friend class SPIRVDecoder;
|
|
|
|
/// Checks the integrity of the object.
|
|
virtual void validate()const {
|
|
assert(Module && "Invalid module");
|
|
assert(OpCode != OpNop && "Invalid op code");
|
|
assert((!hasId() || isValidId(Id)) && "Invalid Id");
|
|
}
|
|
void validateFunctionControlMask(SPIRVWord FCtlMask)const;
|
|
void validateValues(const std::vector<SPIRVId> &)const;
|
|
void validateBuiltin(SPIRVWord, SPIRVWord)const;
|
|
|
|
// By default assume SPIRV 1.0 as required version
|
|
virtual SPIRVWord getRequiredSPIRVVersion() const { return SPIRV_1_0; }
|
|
|
|
virtual std::vector<SPIRVEntry*> getNonLiteralOperands() const {
|
|
return std::vector<SPIRVEntry*>();
|
|
}
|
|
|
|
protected:
|
|
/// An entry may have multiple FuncParamAttr decorations.
|
|
typedef std::multimap<Decoration, const SPIRVDecorate*> DecorateMapType;
|
|
typedef std::map<std::pair<SPIRVWord, Decoration>,
|
|
const SPIRVMemberDecorate*> MemberDecorateMapType;
|
|
|
|
bool canHaveMemberDecorates() const {
|
|
return OpCode == OpTypeStruct ||
|
|
OpCode == OpForward;
|
|
}
|
|
MemberDecorateMapType& getMemberDecorates() {
|
|
assert(canHaveMemberDecorates());
|
|
return MemberDecorates;
|
|
}
|
|
|
|
void updateModuleVersion() const;
|
|
|
|
SPIRVModule *Module;
|
|
Op OpCode;
|
|
SPIRVId Id;
|
|
std::string Name;
|
|
unsigned Attrib;
|
|
SPIRVWord WordCount;
|
|
|
|
DecorateMapType Decorates;
|
|
MemberDecorateMapType MemberDecorates;
|
|
SPIRVLine *Line;
|
|
};
|
|
|
|
class SPIRVEntryNoIdGeneric:public SPIRVEntry {
|
|
public:
|
|
SPIRVEntryNoIdGeneric(SPIRVModule *M, unsigned TheWordCount, Op OC)
|
|
:SPIRVEntry(M, TheWordCount, OC){
|
|
setAttr();
|
|
}
|
|
SPIRVEntryNoIdGeneric(Op OC):SPIRVEntry(OC){
|
|
setAttr();
|
|
}
|
|
protected:
|
|
void setAttr() {
|
|
setHasNoId();
|
|
}
|
|
};
|
|
|
|
template<Op OC>
|
|
class SPIRVEntryNoId:public SPIRVEntryNoIdGeneric {
|
|
public:
|
|
SPIRVEntryNoId(SPIRVModule *M, unsigned TheWordCount)
|
|
:SPIRVEntryNoIdGeneric(M, TheWordCount, OC){}
|
|
SPIRVEntryNoId():SPIRVEntryNoIdGeneric(OC){}
|
|
};
|
|
|
|
template<Op TheOpCode>
|
|
class SPIRVEntryOpCodeOnly:public SPIRVEntryNoId<TheOpCode> {
|
|
public:
|
|
SPIRVEntryOpCodeOnly(){
|
|
SPIRVEntry::WordCount = 1;
|
|
validate();
|
|
}
|
|
protected:
|
|
_SPIRV_DEF_ENCDEC0
|
|
void validate()const {
|
|
assert(isValidId(SPIRVEntry::OpCode));
|
|
}
|
|
};
|
|
|
|
class SPIRVAnnotationGeneric:public SPIRVEntryNoIdGeneric {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVAnnotationGeneric(SPIRVModule *TheModule, unsigned TheWordCount, Op OC,
|
|
SPIRVId TheTarget = SPIRVID_INVALID)
|
|
: SPIRVEntryNoIdGeneric(TheModule, TheWordCount, OC), Target(TheTarget) {}
|
|
// Incomplete constructor
|
|
SPIRVAnnotationGeneric(Op OC):SPIRVEntryNoIdGeneric(OC),
|
|
Target(SPIRVID_INVALID){}
|
|
|
|
SPIRVId getTargetId()const { return Target;}
|
|
SPIRVForward *getOrCreateTarget()const;
|
|
void setTargetId(SPIRVId T) { Target = T;}
|
|
protected:
|
|
SPIRVId Target;
|
|
};
|
|
|
|
template<Op OC>
|
|
class SPIRVAnnotation:public SPIRVAnnotationGeneric {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVAnnotation(const SPIRVEntry *TheTarget, unsigned TheWordCount)
|
|
: SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC,
|
|
TheTarget->getId()) {}
|
|
// Incomplete constructor
|
|
SPIRVAnnotation():SPIRVAnnotationGeneric(OC){}
|
|
};
|
|
|
|
class SPIRVEntryPoint:public SPIRVAnnotation<OpEntryPoint> {
|
|
public:
|
|
SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind,
|
|
SPIRVId TheId, const std::string &TheName);
|
|
SPIRVEntryPoint():ExecModel(ExecutionModelKernel){}
|
|
_SPIRV_DCL_ENCDEC
|
|
protected:
|
|
SPIRVExecutionModelKind ExecModel;
|
|
std::string Name;
|
|
};
|
|
|
|
|
|
class SPIRVName:public SPIRVAnnotation<OpName> {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVName(const SPIRVEntry *TheTarget, const std::string& TheStr);
|
|
// Incomplete constructor
|
|
SPIRVName(){}
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const;
|
|
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVMemberName:public SPIRVAnnotation<OpName> {
|
|
public:
|
|
static const SPIRVWord FixedWC = 3;
|
|
// Complete constructor
|
|
SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber,
|
|
const std::string& TheStr)
|
|
:SPIRVAnnotation(TheTarget, FixedWC + getSizeInWords(TheStr)),
|
|
MemberNumber(TheMemberNumber), Str(TheStr){
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVMemberName():MemberNumber(SPIRVWORD_MAX){}
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const;
|
|
SPIRVWord MemberNumber;
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVString:public SPIRVEntry {
|
|
static const Op OC = OpString;
|
|
static const SPIRVWord FixedWC = 2;
|
|
public:
|
|
SPIRVString(SPIRVModule *M, SPIRVId TheId, const std::string &TheStr)
|
|
:SPIRVEntry(M, FixedWC + getSizeInWords(TheStr), OC, TheId), Str(TheStr){}
|
|
SPIRVString():SPIRVEntry(OC){}
|
|
_SPIRV_DCL_ENCDEC
|
|
const std::string &getStr()const { return Str;}
|
|
protected:
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVLine:public SPIRVAnnotation<OpLine> {
|
|
public:
|
|
static const SPIRVWord WC = 5;
|
|
// Complete constructor
|
|
SPIRVLine(const SPIRVEntry *TheTarget, SPIRVId TheFileName, SPIRVWord TheLine,
|
|
SPIRVWord TheColumn)
|
|
:SPIRVAnnotation(TheTarget, WC), FileName(TheFileName), Line(TheLine),
|
|
Column(TheColumn){
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVLine():FileName(SPIRVID_INVALID), Line(SPIRVWORD_MAX),
|
|
Column(SPIRVWORD_MAX){}
|
|
|
|
SPIRVWord getColumn() const {
|
|
return Column;
|
|
}
|
|
|
|
void setColumn(SPIRVWord column) {
|
|
Column = column;
|
|
}
|
|
|
|
SPIRVId getFileName() const {
|
|
return FileName;
|
|
}
|
|
|
|
const std::string &getFileNameStr() const {
|
|
return get<SPIRVString>(FileName)->getStr();
|
|
}
|
|
|
|
void setFileName(SPIRVId fileName) {
|
|
FileName = fileName;
|
|
}
|
|
|
|
SPIRVWord getLine() const {
|
|
return Line;
|
|
}
|
|
|
|
void setLine(SPIRVWord line) {
|
|
Line = line;
|
|
}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const;
|
|
SPIRVId FileName;
|
|
SPIRVWord Line;
|
|
SPIRVWord Column;
|
|
};
|
|
|
|
class SPIRVExecutionMode:public SPIRVAnnotation<OpExecutionMode> {
|
|
public:
|
|
// Complete constructor for LocalSize, LocalSizeHint
|
|
SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
|
|
SPIRVWord x, SPIRVWord y, SPIRVWord z)
|
|
:SPIRVAnnotation(TheTarget, 6), ExecMode(TheExecMode){
|
|
WordLiterals.push_back(x);
|
|
WordLiterals.push_back(y);
|
|
WordLiterals.push_back(z);
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for VecTypeHint, SubgroupSize, SubgroupsPerWorkgroup
|
|
SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode,
|
|
SPIRVWord code)
|
|
:SPIRVAnnotation(TheTarget, 4), ExecMode(TheExecMode){
|
|
WordLiterals.push_back(code);
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for ContractionOff
|
|
SPIRVExecutionMode(SPIRVEntry *TheTarget, SPIRVExecutionModeKind TheExecMode)
|
|
:SPIRVAnnotation(TheTarget, 3), ExecMode(TheExecMode){
|
|
updateModuleVersion();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVExecutionMode():ExecMode(ExecutionModeInvocations){}
|
|
SPIRVExecutionModeKind getExecutionMode()const { return ExecMode;}
|
|
const std::vector<SPIRVWord>& getLiterals()const { return WordLiterals;}
|
|
SPIRVCapVec getRequiredCapability() const {
|
|
return getCapability(ExecMode);
|
|
}
|
|
|
|
SPIRVWord getRequiredSPIRVVersion() const override {
|
|
switch (ExecMode) {
|
|
case ExecutionModeFinalizer:
|
|
case ExecutionModeInitializer:
|
|
case ExecutionModeSubgroupSize:
|
|
case ExecutionModeSubgroupsPerWorkgroup:
|
|
return SPIRV_1_1;
|
|
|
|
default:
|
|
return SPIRV_1_0;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
SPIRVExecutionModeKind ExecMode;
|
|
std::vector<SPIRVWord> WordLiterals;
|
|
};
|
|
|
|
|
|
class SPIRVComponentExecutionModes {
|
|
typedef std::map<SPIRVExecutionModeKind, SPIRVExecutionMode*>
|
|
SPIRVExecutionModeMap;
|
|
public:
|
|
void addExecutionMode(SPIRVExecutionMode *ExecMode) {
|
|
ExecModes[ExecMode->getExecutionMode()] = ExecMode;
|
|
}
|
|
SPIRVExecutionMode *getExecutionMode(SPIRVExecutionModeKind EMK)const {
|
|
auto Loc = ExecModes.find(EMK);
|
|
if (Loc == ExecModes.end())
|
|
return nullptr;
|
|
return Loc->second;
|
|
}
|
|
protected:
|
|
SPIRVExecutionModeMap ExecModes;
|
|
};
|
|
|
|
class SPIRVExtInstImport:public SPIRVEntry {
|
|
public:
|
|
const static Op OC = OpExtInstImport;
|
|
// Complete constructor
|
|
SPIRVExtInstImport(SPIRVModule *TheModule, SPIRVId TheId,
|
|
const std::string& TheStr);
|
|
// Incomplete constructor
|
|
SPIRVExtInstImport():SPIRVEntry(OC){}
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const;
|
|
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVMemoryModel:public SPIRVEntryNoId<OpMemoryModel> {
|
|
public:
|
|
SPIRVMemoryModel(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
|
|
SPIRVMemoryModel(){}
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const;
|
|
};
|
|
|
|
class SPIRVSource:public SPIRVEntryNoId<OpSource> {
|
|
public:
|
|
SPIRVSource(SPIRVModule *M):SPIRVEntryNoId(M, 3){}
|
|
SPIRVSource(){}
|
|
_SPIRV_DCL_ENCDEC
|
|
};
|
|
|
|
class SPIRVSourceExtension:public SPIRVEntryNoId<OpSourceExtension> {
|
|
public:
|
|
SPIRVSourceExtension(SPIRVModule *M, const std::string &SS);
|
|
SPIRVSourceExtension(){}
|
|
_SPIRV_DCL_ENCDEC
|
|
private:
|
|
std::string S;
|
|
};
|
|
|
|
class SPIRVExtension:public SPIRVEntryNoId<OpExtension> {
|
|
public:
|
|
SPIRVExtension(SPIRVModule *M, const std::string &SS);
|
|
SPIRVExtension(){}
|
|
_SPIRV_DCL_ENCDEC
|
|
private:
|
|
std::string S;
|
|
};
|
|
|
|
class SPIRVCapability:public SPIRVEntryNoId<OpCapability> {
|
|
public:
|
|
SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K);
|
|
SPIRVCapability():Kind(CapabilityMatrix){}
|
|
_SPIRV_DCL_ENCDEC
|
|
|
|
SPIRVWord getRequiredSPIRVVersion() const override {
|
|
switch (Kind) {
|
|
case CapabilityNamedBarrier:
|
|
case CapabilitySubgroupDispatch:
|
|
case CapabilityPipeStorage:
|
|
return SPIRV_1_1;
|
|
|
|
default:
|
|
return SPIRV_1_0;
|
|
}
|
|
}
|
|
private:
|
|
SPIRVCapabilityKind Kind;
|
|
};
|
|
|
|
template<class T>
|
|
T* bcast(SPIRVEntry *E) {
|
|
return static_cast<T*>(E);
|
|
}
|
|
|
|
// ToDo: The following typedef's are place holders for SPIRV entity classes
|
|
// to be implemented.
|
|
// Each time a new class is implemented, remove the corresponding typedef.
|
|
// This is also an indication of how much work is left.
|
|
#define _SPIRV_OP(x, ...) typedef SPIRVEntryOpCodeOnly<Op##x> SPIRV##x;
|
|
_SPIRV_OP(Nop)
|
|
_SPIRV_OP(SourceContinued, 2)
|
|
_SPIRV_OP(TypeMatrix)
|
|
_SPIRV_OP(TypeRuntimeArray)
|
|
_SPIRV_OP(SpecConstantTrue)
|
|
_SPIRV_OP(SpecConstantFalse)
|
|
_SPIRV_OP(SpecConstant)
|
|
_SPIRV_OP(SpecConstantComposite)
|
|
_SPIRV_OP(Image)
|
|
_SPIRV_OP(ImageTexelPointer)
|
|
_SPIRV_OP(CompositeConstruct)
|
|
_SPIRV_OP(ImageSampleDrefImplicitLod)
|
|
_SPIRV_OP(ImageSampleDrefExplicitLod)
|
|
_SPIRV_OP(ImageSampleProjImplicitLod)
|
|
_SPIRV_OP(ImageSampleProjExplicitLod)
|
|
_SPIRV_OP(ImageSampleProjDrefImplicitLod)
|
|
_SPIRV_OP(ImageSampleProjDrefExplicitLod)
|
|
_SPIRV_OP(ImageFetch)
|
|
_SPIRV_OP(ImageGather)
|
|
_SPIRV_OP(ImageDrefGather)
|
|
_SPIRV_OP(QuantizeToF16)
|
|
_SPIRV_OP(Transpose)
|
|
_SPIRV_OP(ArrayLength)
|
|
_SPIRV_OP(SMod)
|
|
_SPIRV_OP(FMod)
|
|
_SPIRV_OP(VectorTimesScalar)
|
|
_SPIRV_OP(MatrixTimesScalar)
|
|
_SPIRV_OP(VectorTimesMatrix)
|
|
_SPIRV_OP(MatrixTimesVector)
|
|
_SPIRV_OP(MatrixTimesMatrix)
|
|
_SPIRV_OP(OuterProduct)
|
|
_SPIRV_OP(IAddCarry)
|
|
_SPIRV_OP(ISubBorrow)
|
|
_SPIRV_OP(SMulExtended)
|
|
_SPIRV_OP(UMulExtended)
|
|
_SPIRV_OP(BitFieldInsert)
|
|
_SPIRV_OP(BitFieldSExtract)
|
|
_SPIRV_OP(BitFieldUExtract)
|
|
_SPIRV_OP(BitReverse)
|
|
_SPIRV_OP(BitCount)
|
|
_SPIRV_OP(DPdx)
|
|
_SPIRV_OP(DPdy)
|
|
_SPIRV_OP(Fwidth)
|
|
_SPIRV_OP(DPdxFine)
|
|
_SPIRV_OP(DPdyFine)
|
|
_SPIRV_OP(FwidthFine)
|
|
_SPIRV_OP(DPdxCoarse)
|
|
_SPIRV_OP(DPdyCoarse)
|
|
_SPIRV_OP(FwidthCoarse)
|
|
_SPIRV_OP(EmitVertex)
|
|
_SPIRV_OP(EndPrimitive)
|
|
_SPIRV_OP(EmitStreamVertex)
|
|
_SPIRV_OP(EndStreamPrimitive)
|
|
_SPIRV_OP(LoopMerge)
|
|
_SPIRV_OP(SelectionMerge)
|
|
_SPIRV_OP(Kill)
|
|
_SPIRV_OP(Unreachable)
|
|
_SPIRV_OP(LifetimeStart)
|
|
_SPIRV_OP(LifetimeStop)
|
|
_SPIRV_OP(ImageSparseSampleImplicitLod, 305)
|
|
_SPIRV_OP(ImageSparseSampleExplicitLod, 306)
|
|
_SPIRV_OP(ImageSparseSampleDrefImplicitLod, 307)
|
|
_SPIRV_OP(ImageSparseSampleDrefExplicitLod, 308)
|
|
_SPIRV_OP(ImageSparseSampleProjImplicitLod, 309)
|
|
_SPIRV_OP(ImageSparseSampleProjExplicitLod, 310)
|
|
_SPIRV_OP(ImageSparseSampleProjDrefImplicitLod, 311)
|
|
_SPIRV_OP(ImageSparseSampleProjDrefExplicitLod, 312)
|
|
_SPIRV_OP(ImageSparseFetch, 313)
|
|
_SPIRV_OP(ImageSparseGather, 314)
|
|
_SPIRV_OP(ImageSparseDrefGather, 315)
|
|
_SPIRV_OP(ImageSparseTexelsResident, 316)
|
|
_SPIRV_OP(NoLine, 317)
|
|
_SPIRV_OP(TypeNamedBarrier)
|
|
_SPIRV_OP(NamedBarrierInitialize)
|
|
_SPIRV_OP(MemoryNamedBarrier)
|
|
_SPIRV_OP(GetKernelMaxNumSubgroups)
|
|
_SPIRV_OP(GetKernelLocalSizeForSubgroupCount)
|
|
_SPIRV_OP(SizeOf)
|
|
#undef _SPIRV_OP
|
|
|
|
}
|
|
#endif /* SPIRVENTRY_HPP_ */
|