CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
1141 lines
44 KiB
C++
1141 lines
44 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 SPIRV_LIBSPIRV_SPIRVENTRY_H
|
|
#define SPIRV_LIBSPIRV_SPIRVENTRY_H
|
|
|
|
#include "SPIRVEnum.h"
|
|
#include "SPIRVError.h"
|
|
#include "SPIRVIsValidEnum.h"
|
|
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace SPIRV {
|
|
|
|
class SPIRVModule;
|
|
class SPIRVEncoder;
|
|
class SPIRVDecoder;
|
|
class SPIRVType;
|
|
class SPIRVValue;
|
|
class SPIRVDecorate;
|
|
class SPIRVDecorateId;
|
|
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 override; \
|
|
void decode(std::istream &I) override;
|
|
|
|
#define _REQ_SPIRV_VER(Version) \
|
|
VersionNumber 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 override {} \
|
|
void decode(std::istream &I) override {}
|
|
#define _SPIRV_DEF_ENCDEC1(x) \
|
|
void encode(spv_ostream &O) const override { getEncoder(O) << (x); } \
|
|
void decode(std::istream &I) override { getDecoder(I) >> (x); }
|
|
#define _SPIRV_DEF_ENCDEC2(x, y) \
|
|
void encode(spv_ostream &O) const override { getEncoder(O) << (x) << (y); } \
|
|
void decode(std::istream &I) override { getDecoder(I) >> (x) >> (y); }
|
|
#define _SPIRV_DEF_ENCDEC3(x, y, z) \
|
|
void encode(spv_ostream &O) const override { \
|
|
getEncoder(O) << (x) << (y) << (z); \
|
|
} \
|
|
void decode(std::istream &I) override { getDecoder(I) >> (x) >> (y) >> (z); }
|
|
#define _SPIRV_DEF_ENCDEC4(x, y, z, u) \
|
|
void encode(spv_ostream &O) const override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
getDecoder(I) >> (x) >> (y) >> (z) >> (u); \
|
|
}
|
|
#define _SPIRV_DEF_ENCDEC5(x, y, z, u, v) \
|
|
void encode(spv_ostream &O) const override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u) << (v); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
getDecoder(I) >> (x) >> (y) >> (z) >> (u) >> (v); \
|
|
}
|
|
#define _SPIRV_DEF_ENCDEC6(x, y, z, u, v, w) \
|
|
void encode(spv_ostream &O) const override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
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 override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
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 override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
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 override { \
|
|
getEncoder(O) << (x) << (y) << (z) << (u) << (v) << (w) << (r) << (s) \
|
|
<< (t); \
|
|
} \
|
|
void decode(std::istream &I) override { \
|
|
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) {
|
|
SPIRVEntry::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) {
|
|
SPIRVEntry::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 {
|
|
// NOLINTNEXTLINE
|
|
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;
|
|
}
|
|
std::shared_ptr<const SPIRVLine> getLine() const { return Line; }
|
|
std::shared_ptr<const SPIRVExtInst> getDebugLine() const { return DebugLine; }
|
|
SPIRVLinkageTypeKind getLinkageType() const;
|
|
Op getOpCode() const { return OpCode; }
|
|
SPIRVModule *getModule() const { return Module; }
|
|
virtual SPIRVCapVec getRequiredCapability() const { return SPIRVCapVec(); }
|
|
virtual std::optional<ExtensionID> getRequiredExtension() const { return {}; }
|
|
const std::string &getName() const { return Name; }
|
|
size_t getNumDecorations() const { return Decorates.size(); }
|
|
bool hasDecorate(Decoration Kind, size_t Index = 0,
|
|
SPIRVWord *Result = 0) const;
|
|
bool hasDecorateId(Decoration Kind, size_t Index = 0,
|
|
SPIRVId *Result = 0) const;
|
|
bool hasMemberDecorate(Decoration Kind, size_t Index = 0,
|
|
SPIRVWord MemberNumber = 0,
|
|
SPIRVWord *Result = 0) const;
|
|
std::vector<SPIRVWord> getDecorationLiterals(Decoration Kind) const;
|
|
std::vector<SPIRVId> getDecorationIdLiterals(Decoration Kind) const;
|
|
std::vector<SPIRVWord>
|
|
getMemberDecorationLiterals(Decoration Kind, SPIRVWord MemberNumber) const;
|
|
std::vector<std::string> getDecorationStringLiteral(Decoration Kind) const;
|
|
std::vector<std::vector<std::string>>
|
|
getAllDecorationStringLiterals(Decoration Kind) const;
|
|
std::vector<std::vector<std::string>>
|
|
getAllMemberDecorationStringLiterals(Decoration Kind,
|
|
SPIRVWord MemberNumber) const;
|
|
std::vector<std::string>
|
|
getMemberDecorationStringLiteral(Decoration Kind,
|
|
SPIRVWord MemberNumber) const;
|
|
std::set<SPIRVWord> getDecorate(Decoration Kind, size_t Index = 0) const;
|
|
std::vector<SPIRVDecorate const *> getDecorations(Decoration Kind) const;
|
|
std::vector<SPIRVDecorate const *> getDecorations() const;
|
|
std::set<SPIRVId> getDecorateId(Decoration Kind, size_t Index = 0) const;
|
|
std::vector<SPIRVDecorateId const *> getDecorationIds(Decoration Kind) 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 isExtInst() const { return OpCode == OpExtInst; }
|
|
bool isExtInst(const SPIRVExtInstSetKind InstSet) const;
|
|
bool isExtInst(const SPIRVExtInstSetKind InstSet,
|
|
const SPIRVWord ExtOp) const;
|
|
bool isDecorate() const { return OpCode == OpDecorate; }
|
|
bool isDecorateId() const { return OpCode == OpDecorateId; }
|
|
bool isMemberDecorate() const { return OpCode == OpMemberDecorate; }
|
|
bool isForward() const { return OpCode == internal::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 || OpCode == OpUntypedVariableKHR;
|
|
}
|
|
bool isUntypedVariable() const { return OpCode == OpUntypedVariableKHR; }
|
|
bool isEndOfBlock() const;
|
|
virtual bool isInst() const { return false; }
|
|
virtual bool isOperandLiteral(unsigned Index) const {
|
|
assert(0 && "not implemented");
|
|
return false;
|
|
}
|
|
virtual bool isImplemented() const { return true; }
|
|
|
|
void addDecorate(SPIRVDecorate *);
|
|
void addDecorate(SPIRVDecorateId *);
|
|
void addDecorate(Decoration Kind);
|
|
void addDecorate(Decoration Kind, SPIRVWord Literal);
|
|
void eraseDecorate(Decoration);
|
|
void eraseDecorateId(Decoration);
|
|
void addMemberDecorate(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(const std::shared_ptr<const SPIRVLine> &L);
|
|
void setDebugLine(const std::shared_ptr<const SPIRVExtInst> &DL);
|
|
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 takeDecorateIds(SPIRVEntry *);
|
|
void takeMemberDecorates(SPIRVEntry *);
|
|
void replaceTargetIdInDecorates(SPIRVId);
|
|
|
|
/// 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> createUnique(Op);
|
|
|
|
/// Create an empty extended instruction.
|
|
static std::unique_ptr<SPIRVExtInst> createUnique(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 encodeLine(spv_ostream &O) const;
|
|
virtual void encodeDebugLine(spv_ostream &O) const;
|
|
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");
|
|
if (WordCount > 65535) {
|
|
std::stringstream SS;
|
|
SS << "Id: " << Id << ", OpCode: " << OpCodeNameMap::map(OpCode)
|
|
<< ", Name: \"" << Name << "\"\n";
|
|
getErrorLog().checkError(
|
|
false, SPIRVEC_InvalidWordCount,
|
|
"Can't encode instruction with word count greater than 65535:\n" +
|
|
SS.str());
|
|
}
|
|
}
|
|
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 VersionNumber getRequiredSPIRVVersion() const {
|
|
return VersionNumber::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::multimap<Decoration, const SPIRVDecorateId *> DecorateIdMapType;
|
|
typedef std::multimap<std::pair<SPIRVWord, Decoration>,
|
|
const SPIRVMemberDecorate *>
|
|
MemberDecorateMapType;
|
|
|
|
bool canHaveMemberDecorates() const {
|
|
return OpCode == OpTypeStruct || OpCode == internal::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;
|
|
DecorateIdMapType DecorateIds;
|
|
MemberDecorateMapType MemberDecorates;
|
|
std::shared_ptr<const SPIRVLine> Line;
|
|
std::shared_ptr<const SPIRVExtInst> DebugLine;
|
|
};
|
|
|
|
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 override { assert(isValidId(SPIRVEntry::OpCode)); }
|
|
};
|
|
|
|
template <Op TheOpCode>
|
|
class SPIRVEntryUnimplemented : public SPIRVEntryNoId<TheOpCode> {
|
|
public:
|
|
SPIRVEntryUnimplemented() {
|
|
SPIRVEntry::WordCount = 1;
|
|
validate();
|
|
}
|
|
bool isImplemented() const override { return false; }
|
|
|
|
protected:
|
|
_SPIRV_DEF_ENCDEC0
|
|
void validate() const override { 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;
|
|
};
|
|
|
|
class SPIRVAnnotation : public SPIRVAnnotationGeneric {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVAnnotation(Op OC, const SPIRVEntry *TheTarget, unsigned TheWordCount)
|
|
: SPIRVAnnotationGeneric(TheTarget->getModule(), TheWordCount, OC,
|
|
TheTarget->getId()) {}
|
|
// Incomplete constructors
|
|
SPIRVAnnotation(Op OC) : SPIRVAnnotationGeneric(OC) {}
|
|
SPIRVAnnotation() : SPIRVAnnotationGeneric(OpNop) {}
|
|
};
|
|
|
|
class SPIRVEntryPoint : public SPIRVAnnotation {
|
|
public:
|
|
static const SPIRVWord FixedWC = 4;
|
|
SPIRVEntryPoint(SPIRVModule *TheModule, SPIRVExecutionModelKind,
|
|
SPIRVId TheId, const std::string &TheName,
|
|
std::vector<SPIRVId> Variables);
|
|
SPIRVEntryPoint() : SPIRVAnnotation(OpEntryPoint) {}
|
|
|
|
_SPIRV_DCL_ENCDEC
|
|
protected:
|
|
SPIRVExecutionModelKind ExecModel = ExecutionModelMax;
|
|
std::string Name;
|
|
|
|
private:
|
|
std::vector<SPIRVId> Variables;
|
|
};
|
|
|
|
class SPIRVName : public SPIRVAnnotation {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVName(const SPIRVEntry *TheTarget, const std::string &TheStr);
|
|
// Incomplete constructor
|
|
SPIRVName() : SPIRVAnnotation(OpName) {}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const override;
|
|
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVMemberName : public SPIRVAnnotation {
|
|
public:
|
|
static const SPIRVWord FixedWC = 3;
|
|
// Complete constructor
|
|
SPIRVMemberName(const SPIRVEntry *TheTarget, SPIRVWord TheMemberNumber,
|
|
const std::string &TheStr)
|
|
: SPIRVAnnotation(OpName, TheTarget, FixedWC + getSizeInWords(TheStr)),
|
|
MemberNumber(TheMemberNumber), Str(TheStr) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVMemberName() : SPIRVAnnotation(OpName), MemberNumber(SPIRVWORD_MAX) {}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const override;
|
|
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 SPIRVEntry {
|
|
public:
|
|
static const SPIRVWord WC = 4;
|
|
// Complete constructor
|
|
SPIRVLine(SPIRVModule *M, SPIRVId TheFileName, SPIRVWord TheLine,
|
|
SPIRVWord TheColumn)
|
|
: SPIRVEntry(M, WC, OpLine), FileName(TheFileName), Line(TheLine),
|
|
Column(TheColumn) {
|
|
Attrib = SPIRVEA_NOID | SPIRVEA_NOTYPE;
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVLine()
|
|
: SPIRVEntry(OpLine), FileName(SPIRVID_INVALID), Line(SPIRVWORD_MAX),
|
|
Column(SPIRVWORD_MAX) {
|
|
Attrib = SPIRVEA_NOID | SPIRVEA_NOTYPE;
|
|
}
|
|
|
|
SPIRVWord getColumn() const { return Column; }
|
|
|
|
void setColumn(const SPIRVWord Column) { this->Column = Column; }
|
|
|
|
SPIRVId getFileName() const { return FileName; }
|
|
|
|
const std::string &getFileNameStr() const {
|
|
return get<SPIRVString>(FileName)->getStr();
|
|
}
|
|
|
|
void setFileName(const SPIRVId FileName) { this->FileName = FileName; }
|
|
|
|
SPIRVWord getLine() const { return Line; }
|
|
|
|
void setLine(const SPIRVWord Line) { this->Line = Line; }
|
|
|
|
bool operator!=(const SPIRVLine &O) const {
|
|
return !equals(O.FileName, O.Line, O.Column);
|
|
}
|
|
|
|
bool equals(const SPIRVId TheFileName, const SPIRVWord TheLine,
|
|
const SPIRVWord TheColumn) const {
|
|
return FileName == TheFileName && Line == TheLine && Column == TheColumn;
|
|
}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const override;
|
|
SPIRVId FileName;
|
|
SPIRVWord Line;
|
|
SPIRVWord Column;
|
|
};
|
|
|
|
class SPIRVExecutionMode : public SPIRVAnnotation {
|
|
public:
|
|
// Complete constructor for LocalSize, LocalSizeHint
|
|
SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord X,
|
|
SPIRVWord Y, SPIRVWord Z)
|
|
: SPIRVAnnotation(OC, TheTarget, 6), ExecMode(TheExecMode) {
|
|
WordLiterals.push_back(X);
|
|
WordLiterals.push_back(Y);
|
|
WordLiterals.push_back(Z);
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for FPFastMathDefault.
|
|
SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord TargetType,
|
|
SPIRVWord FastMathMode)
|
|
: SPIRVAnnotation(OC, TheTarget, 5), ExecMode(TheExecMode) {
|
|
assert(OC == OpExecutionModeId);
|
|
assert(TheExecMode == ExecutionModeFPFastMathDefault);
|
|
WordLiterals.push_back(TargetType);
|
|
WordLiterals.push_back(FastMathMode);
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for VecTypeHint, SubgroupSize, SubgroupsPerWorkgroup
|
|
SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord Code)
|
|
: SPIRVAnnotation(OC, TheTarget, 4), ExecMode(TheExecMode) {
|
|
WordLiterals.push_back(Code);
|
|
}
|
|
// Complete constructor for ContractionOff
|
|
SPIRVExecutionMode(Op OC, SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode)
|
|
: SPIRVAnnotation(OC, TheTarget, 3), ExecMode(TheExecMode) {
|
|
updateModuleVersion();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVExecutionMode()
|
|
: SPIRVAnnotation(OpExecutionMode), ExecMode(ExecutionModeInvocations) {}
|
|
SPIRVExecutionModeKind getExecutionMode() const { return ExecMode; }
|
|
const std::vector<SPIRVWord> &getLiterals() const { return WordLiterals; }
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
return getCapability(ExecMode);
|
|
}
|
|
|
|
VersionNumber getRequiredSPIRVVersion() const override {
|
|
switch (ExecMode) {
|
|
case ExecutionModeFinalizer:
|
|
case ExecutionModeInitializer:
|
|
case ExecutionModeSubgroupSize:
|
|
case ExecutionModeSubgroupsPerWorkgroup:
|
|
return VersionNumber::SPIRV_1_1;
|
|
|
|
default:
|
|
return VersionNumber::SPIRV_1_0;
|
|
}
|
|
}
|
|
|
|
std::optional<ExtensionID> getRequiredExtension() const override {
|
|
switch (static_cast<unsigned>(ExecMode)) {
|
|
case ExecutionModeMaximumRegistersINTEL:
|
|
case ExecutionModeMaximumRegistersIdINTEL:
|
|
case ExecutionModeNamedMaximumRegistersINTEL:
|
|
return ExtensionID::SPV_INTEL_maximum_registers;
|
|
case ExecutionModeArithmeticPoisonKHR:
|
|
return ExtensionID::SPV_KHR_poison_freeze;
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
protected:
|
|
_SPIRV_DCL_ENCDEC
|
|
SPIRVExecutionModeKind ExecMode;
|
|
std::vector<SPIRVWord> WordLiterals;
|
|
};
|
|
|
|
class SPIRVExecutionModeId : public SPIRVExecutionMode {
|
|
public:
|
|
// Complete constructor for LocalSizeId, LocalSizeHintId
|
|
SPIRVExecutionModeId(SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord X,
|
|
SPIRVWord Y, SPIRVWord Z)
|
|
: SPIRVExecutionMode(OpExecutionModeId, TheTarget, TheExecMode, X, Y, Z) {
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for FPFastMathDefault.
|
|
SPIRVExecutionModeId(SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord TargetType,
|
|
SPIRVWord FastMathMode)
|
|
: SPIRVExecutionMode(OpExecutionModeId, TheTarget, TheExecMode,
|
|
TargetType, FastMathMode) {
|
|
assert(TheExecMode == ExecutionModeFPFastMathDefault);
|
|
updateModuleVersion();
|
|
}
|
|
// Complete constructor for SubgroupsPerWorkgroupId
|
|
SPIRVExecutionModeId(SPIRVEntry *TheTarget,
|
|
SPIRVExecutionModeKind TheExecMode, SPIRVWord Code)
|
|
: SPIRVExecutionMode(OpExecutionModeId, TheTarget, TheExecMode, Code) {
|
|
updateModuleVersion();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVExecutionModeId() : SPIRVExecutionMode() {}
|
|
VersionNumber getRequiredSPIRVVersion() const override {
|
|
return VersionNumber::SPIRV_1_2;
|
|
}
|
|
};
|
|
|
|
class SPIRVComponentExecutionModes {
|
|
typedef std::multimap<SPIRVExecutionModeKind, SPIRVExecutionMode *>
|
|
SPIRVExecutionModeMap;
|
|
typedef std::pair<SPIRVExecutionModeMap::const_iterator,
|
|
SPIRVExecutionModeMap::const_iterator>
|
|
SPIRVExecutionModeRange;
|
|
|
|
public:
|
|
void addExecutionMode(SPIRVExecutionMode *ExecMode) {
|
|
// There should not be more than 1 execution mode kind except the ones
|
|
// mentioned in SPV_KHR_float_controls and SPV_INTEL_float_controls2.
|
|
#ifndef NDEBUG
|
|
auto IsDenorm = [](auto EMK) {
|
|
return EMK == ExecutionModeDenormPreserve ||
|
|
EMK == ExecutionModeDenormFlushToZero;
|
|
};
|
|
auto IsRoundingMode = [](auto EMK) {
|
|
return EMK == ExecutionModeRoundingModeRTE ||
|
|
EMK == ExecutionModeRoundingModeRTZ ||
|
|
EMK == ExecutionModeRoundingModeRTPINTEL ||
|
|
EMK == ExecutionModeRoundingModeRTNINTEL;
|
|
};
|
|
auto IsFPMode = [](auto EMK) {
|
|
return EMK == ExecutionModeFloatingPointModeALTINTEL ||
|
|
EMK == ExecutionModeFloatingPointModeIEEEINTEL;
|
|
};
|
|
auto IsOtherFP = [](auto EMK) {
|
|
return EMK == ExecutionModeSignedZeroInfNanPreserve;
|
|
};
|
|
auto IsFastMathDefault = [](auto EMK) {
|
|
return EMK == ExecutionModeFPFastMathDefault;
|
|
};
|
|
auto IsFloatControl = [&](auto EMK) {
|
|
return IsDenorm(EMK) || IsRoundingMode(EMK) || IsFPMode(EMK) ||
|
|
IsOtherFP(EMK) || IsFastMathDefault(EMK);
|
|
};
|
|
auto IsMaxRegisters = [&](auto EMK) {
|
|
return EMK == ExecutionModeMaximumRegistersINTEL ||
|
|
EMK == ExecutionModeMaximumRegistersIdINTEL ||
|
|
EMK == ExecutionModeNamedMaximumRegistersINTEL;
|
|
};
|
|
auto IsCompatible = [&](SPIRVExecutionMode *EM0, SPIRVExecutionMode *EM1) {
|
|
if (EM0->getTargetId() != EM1->getTargetId())
|
|
return true;
|
|
auto EMK0 = EM0->getExecutionMode();
|
|
auto EMK1 = EM1->getExecutionMode();
|
|
if (!IsFloatControl(EMK0) || !IsFloatControl(EMK1))
|
|
return EMK0 != EMK1;
|
|
auto TW0 = EM0->getLiterals().at(0);
|
|
auto TW1 = EM1->getLiterals().at(0);
|
|
if (TW0 != TW1)
|
|
return true;
|
|
return !(IsDenorm(EMK0) && IsDenorm(EMK1)) &&
|
|
!(IsRoundingMode(EMK0) && IsRoundingMode(EMK1)) &&
|
|
!(IsFPMode(EMK0) && IsFPMode(EMK1)) &&
|
|
!(IsMaxRegisters(EMK0) && IsMaxRegisters(EMK1));
|
|
};
|
|
for (auto I = ExecModes.begin(); I != ExecModes.end(); ++I) {
|
|
assert(IsCompatible(ExecMode, (*I).second) &&
|
|
"Found incompatible execution modes");
|
|
}
|
|
#endif // !NDEBUG
|
|
SPIRVExecutionModeKind EMK = ExecMode->getExecutionMode();
|
|
ExecModes.emplace(EMK, ExecMode);
|
|
}
|
|
SPIRVExecutionMode *getExecutionMode(SPIRVExecutionModeKind EMK) const {
|
|
auto Loc = ExecModes.find(EMK);
|
|
if (Loc == ExecModes.end())
|
|
return nullptr;
|
|
return Loc->second;
|
|
}
|
|
SPIRVExecutionModeId *getExecutionModeId(SPIRVExecutionModeKind EMK) const {
|
|
auto Loc = ExecModes.find(EMK);
|
|
if (Loc == ExecModes.end())
|
|
return nullptr;
|
|
return static_cast<SPIRVExecutionModeId *>(Loc->second);
|
|
}
|
|
SPIRVExecutionModeRange
|
|
getExecutionModeRange(SPIRVExecutionModeKind EMK) const {
|
|
return ExecModes.equal_range(EMK);
|
|
}
|
|
|
|
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 override;
|
|
|
|
std::string Str;
|
|
};
|
|
|
|
class SPIRVMemoryModel : public SPIRVEntryNoId<OpMemoryModel> {
|
|
public:
|
|
SPIRVMemoryModel(SPIRVModule *M) : SPIRVEntryNoId(M, 3) {}
|
|
SPIRVMemoryModel() {}
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const override;
|
|
};
|
|
|
|
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() {}
|
|
|
|
std::string getExtensionName() const { return S; }
|
|
|
|
_SPIRV_DCL_ENCDEC
|
|
private:
|
|
std::string S;
|
|
};
|
|
|
|
class SPIRVCapability : public SPIRVEntryNoId<OpCapability> {
|
|
public:
|
|
SPIRVCapability(SPIRVModule *M, SPIRVCapabilityKind K);
|
|
SPIRVCapability() : Kind(CapabilityMatrix) {}
|
|
_SPIRV_DCL_ENCDEC
|
|
|
|
VersionNumber getRequiredSPIRVVersion() const override {
|
|
switch (Kind) {
|
|
case CapabilityGroupNonUniform:
|
|
case CapabilityGroupNonUniformVote:
|
|
case CapabilityGroupNonUniformArithmetic:
|
|
case CapabilityGroupNonUniformBallot:
|
|
case CapabilityGroupNonUniformShuffle:
|
|
case CapabilityGroupNonUniformShuffleRelative:
|
|
case CapabilityGroupNonUniformClustered:
|
|
return VersionNumber::SPIRV_1_3;
|
|
|
|
case CapabilityFloatControls2:
|
|
return VersionNumber::SPIRV_1_2;
|
|
|
|
case CapabilityNamedBarrier:
|
|
case CapabilitySubgroupDispatch:
|
|
case CapabilityPipeStorage:
|
|
return VersionNumber::SPIRV_1_1;
|
|
|
|
default:
|
|
return VersionNumber::SPIRV_1_0;
|
|
}
|
|
}
|
|
|
|
std::optional<ExtensionID> getRequiredExtension() const override {
|
|
switch (static_cast<unsigned>(Kind)) {
|
|
case CapabilityRoundToInfinityINTEL:
|
|
case CapabilityFloatingPointModeINTEL:
|
|
case CapabilityFunctionFloatControlINTEL:
|
|
return ExtensionID::SPV_INTEL_float_controls2;
|
|
case CapabilityVectorComputeINTEL:
|
|
case CapabilityVectorAnyINTEL:
|
|
return ExtensionID::SPV_INTEL_vector_compute;
|
|
case internal::CapabilitySubgroupRequirementsINTEL:
|
|
return ExtensionID::SPV_INTEL_subgroup_requirements;
|
|
case CapabilityFPFastMathModeINTEL:
|
|
return ExtensionID::SPV_INTEL_fp_fast_math_mode;
|
|
case CapabilityFunctionVariantsINTEL:
|
|
case CapabilitySpecConditionalINTEL:
|
|
return ExtensionID::SPV_INTEL_function_variants;
|
|
case internal::CapabilityBFloat16ArithmeticINTEL:
|
|
return ExtensionID::SPV_INTEL_bfloat16_arithmetic;
|
|
case internal::CapabilityDeviceBarrierINTEL:
|
|
return ExtensionID::SPV_INTEL_device_barrier;
|
|
case CapabilityFloatControls2:
|
|
return ExtensionID::SPV_KHR_float_controls2;
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
private:
|
|
SPIRVCapabilityKind Kind;
|
|
};
|
|
|
|
template <class T> T *bcast(SPIRVEntry *E) { return static_cast<T *>(E); }
|
|
|
|
template <spv::Op OC> bool isa(SPIRVEntry *E) {
|
|
return E ? E->getOpCode() == OC : false;
|
|
}
|
|
|
|
template <spv::Op OC>
|
|
class SPIRVContinuedInstINTELBase : public SPIRVEntryNoId<OC> {
|
|
public:
|
|
template <spv::Op _OC, class T = void>
|
|
using EnableIfCompositeConst =
|
|
typename std::enable_if_t<_OC == OpConstantCompositeContinuedINTEL ||
|
|
_OC ==
|
|
OpSpecConstantCompositeContinuedINTEL,
|
|
T>;
|
|
// Complete constructor
|
|
SPIRVContinuedInstINTELBase(SPIRVModule *M,
|
|
const std::vector<SPIRVValue *> &TheElements)
|
|
: SPIRVEntryNoId<OC>(M, TheElements.size() + 1) {
|
|
|
|
Elements = SPIRVEntry::getIds(TheElements);
|
|
validate();
|
|
}
|
|
|
|
SPIRVContinuedInstINTELBase(SPIRVModule *M, unsigned NumOfElements)
|
|
: SPIRVEntryNoId<OC>(M, NumOfElements + 1) {
|
|
Elements.resize(NumOfElements, SPIRVID_INVALID);
|
|
validate();
|
|
}
|
|
|
|
// Incomplete constructor
|
|
SPIRVContinuedInstINTELBase() : SPIRVEntryNoId<OC>() {}
|
|
|
|
template <spv::Op OPC = OC>
|
|
EnableIfCompositeConst<OPC, std::vector<SPIRVValue *>> getElements() const {
|
|
return SPIRVEntry::getValues(Elements);
|
|
}
|
|
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
return getVec(CapabilityLongCompositesINTEL);
|
|
}
|
|
|
|
std::optional<ExtensionID> getRequiredExtension() const override {
|
|
return ExtensionID::SPV_INTEL_long_composites;
|
|
}
|
|
|
|
SPIRVWord getNumElements() const { return Elements.size(); }
|
|
|
|
protected:
|
|
void validate() const override;
|
|
void setWordCount(SPIRVWord WordCount) override {
|
|
SPIRVEntry::setWordCount(WordCount);
|
|
this->SPIRVCK(WordCount, InvalidWordCount, "");
|
|
Elements.resize(WordCount - 1);
|
|
}
|
|
_SPIRV_DCL_ENCDEC
|
|
|
|
std::vector<SPIRVId> Elements;
|
|
};
|
|
|
|
class SPIRVTypeStructContinuedINTEL
|
|
: public SPIRVContinuedInstINTELBase<OpTypeStructContinuedINTEL> {
|
|
public:
|
|
constexpr static Op OC = OpTypeStructContinuedINTEL;
|
|
// Complete constructor
|
|
SPIRVTypeStructContinuedINTEL(SPIRVModule *M, unsigned NumOfElements)
|
|
: SPIRVContinuedInstINTELBase<OC>(M, NumOfElements) {}
|
|
|
|
// Incomplete constructor
|
|
SPIRVTypeStructContinuedINTEL() : SPIRVContinuedInstINTELBase<OC>() {}
|
|
|
|
void setElementId(size_t I, SPIRVId Id) { Elements[I] = Id; }
|
|
|
|
SPIRVType *getMemberType(size_t I) const;
|
|
};
|
|
|
|
using SPIRVConstantCompositeContinuedINTEL =
|
|
SPIRVContinuedInstINTELBase<OpConstantCompositeContinuedINTEL>;
|
|
using SPIRVSpecConstantCompositeContinuedINTEL =
|
|
SPIRVContinuedInstINTELBase<OpSpecConstantCompositeContinuedINTEL>;
|
|
|
|
template <spv::Op OpCode> struct InstToContinued;
|
|
|
|
template <> struct InstToContinued<OpTypeStruct> {
|
|
using Type = SPIRVTypeStructContinuedINTEL *;
|
|
constexpr static spv::Op OpCode = OpTypeStructContinuedINTEL;
|
|
};
|
|
|
|
template <> struct InstToContinued<OpConstantComposite> {
|
|
using Type = SPIRVConstantCompositeContinuedINTEL *;
|
|
constexpr static spv::Op OpCode = OpConstantCompositeContinuedINTEL;
|
|
};
|
|
|
|
template <> struct InstToContinued<OpSpecConstantComposite> {
|
|
using Type = SPIRVSpecConstantCompositeContinuedINTEL *;
|
|
constexpr static spv::Op OpCode = OpSpecConstantCompositeContinuedINTEL;
|
|
};
|
|
|
|
class SPIRVModuleProcessed : public SPIRVEntryNoId<OpModuleProcessed> {
|
|
public:
|
|
SPIRVModuleProcessed(SPIRVModule *M, const std::string &Process)
|
|
: SPIRVEntryNoId(M, FixedWC + getSizeInWords(Process)),
|
|
ProcessStr(Process) {
|
|
updateModuleVersion();
|
|
}
|
|
SPIRVModuleProcessed() { updateModuleVersion(); }
|
|
_SPIRV_DCL_ENCDEC
|
|
void validate() const override;
|
|
VersionNumber getRequiredSPIRVVersion() const override {
|
|
return VersionNumber::SPIRV_1_1;
|
|
}
|
|
|
|
std::string getProcessStr();
|
|
|
|
private:
|
|
std::string ProcessStr;
|
|
static const SPIRVWord FixedWC = 1;
|
|
};
|
|
|
|
// 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 SPIRVEntryUnimplemented<Op##x> SPIRV##x;
|
|
_SPIRV_OP(Nop)
|
|
_SPIRV_OP(SourceContinued)
|
|
_SPIRV_OP(TypeRuntimeArray)
|
|
_SPIRV_OP(ImageTexelPointer)
|
|
_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(ArrayLength)
|
|
_SPIRV_OP(OuterProduct)
|
|
_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(Kill)
|
|
_SPIRV_OP(ImageSparseSampleImplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleExplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleDrefImplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleDrefExplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleProjImplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleProjExplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleProjDrefImplicitLod)
|
|
_SPIRV_OP(ImageSparseSampleProjDrefExplicitLod)
|
|
_SPIRV_OP(ImageSparseFetch)
|
|
_SPIRV_OP(ImageSparseGather)
|
|
_SPIRV_OP(ImageSparseDrefGather)
|
|
_SPIRV_OP(ImageSparseTexelsResident)
|
|
_SPIRV_OP(NoLine)
|
|
_SPIRV_OP(TypeNamedBarrier)
|
|
_SPIRV_OP(NamedBarrierInitialize)
|
|
_SPIRV_OP(MemoryNamedBarrier)
|
|
_SPIRV_OP(GetKernelMaxNumSubgroups)
|
|
_SPIRV_OP(GetKernelLocalSizeForSubgroupCount)
|
|
#undef _SPIRV_OP
|
|
|
|
} // namespace SPIRV
|
|
#endif // SPIRV_LIBSPIRV_SPIRVENTRY_H
|