//===- 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_ */