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
494 lines
16 KiB
C++
494 lines
16 KiB
C++
//===- SPIRVValue.h - Class to represent a SPIR-V Value ---------*- 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 values defined in SPIR-V spec with op codes.
|
|
///
|
|
/// The name of the SPIR-V values follow the op code name in the spec.
|
|
/// This is for readability and ease of using macro to handle types.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SPIRV_LIBSPIRV_SPIRVVALUE_H
|
|
#define SPIRV_LIBSPIRV_SPIRVVALUE_H
|
|
|
|
#include "SPIRVDecorate.h"
|
|
#include "SPIRVEntry.h"
|
|
#include "SPIRVType.h"
|
|
|
|
namespace llvm {
|
|
class APInt;
|
|
} // namespace llvm
|
|
|
|
#include <iostream>
|
|
|
|
namespace SPIRV {
|
|
|
|
class SPIRVValue : public SPIRVEntry {
|
|
public:
|
|
// Complete constructor for value with id and type
|
|
SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
|
|
SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(TheType) {
|
|
validate();
|
|
}
|
|
// Complete constructor for value with type but without id
|
|
SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode,
|
|
SPIRVType *TheType)
|
|
: SPIRVEntry(M, TheWordCount, TheOpCode), Type(TheType) {
|
|
setHasNoId();
|
|
SPIRVValue::validate();
|
|
}
|
|
// Complete constructor for value with id but without type
|
|
SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode, SPIRVId TheId)
|
|
: SPIRVEntry(M, TheWordCount, TheOpCode, TheId), Type(NULL) {
|
|
setHasNoType();
|
|
SPIRVValue::validate();
|
|
}
|
|
// Complete constructor for value without id and type
|
|
SPIRVValue(SPIRVModule *M, unsigned TheWordCount, Op TheOpCode)
|
|
: SPIRVEntry(M, TheWordCount, TheOpCode), Type(NULL) {
|
|
setHasNoId();
|
|
setHasNoType();
|
|
SPIRVValue::validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVValue(Op TheOpCode) : SPIRVEntry(TheOpCode), Type(NULL) {}
|
|
|
|
bool hasType() const { return !(Attrib & SPIRVEA_NOTYPE); }
|
|
SPIRVType *getType() const {
|
|
assert(hasType() && "value has no type");
|
|
return Type;
|
|
}
|
|
bool isVolatile() const;
|
|
bool hasAlignment(SPIRVWord *Result = 0) const;
|
|
bool hasNoSignedWrap() const;
|
|
bool hasNoUnsignedWrap() const;
|
|
|
|
void setAlignment(SPIRVWord);
|
|
void setVolatile(bool IsVolatile);
|
|
|
|
template <spv::Decoration NoIntegerWrapDecoration>
|
|
void setNoIntegerDecorationWrap(bool HasNoIntegerWrap);
|
|
|
|
void setFPFastMathMode(SPIRVWord FPFastMathMode);
|
|
|
|
void validate() const override {
|
|
SPIRVEntry::validate();
|
|
assert((!hasType() || Type) && "Invalid type");
|
|
}
|
|
|
|
void setType(SPIRVType *Ty) {
|
|
Type = Ty;
|
|
assert(!Ty || !Ty->isTypeVoid() || OpCode == OpFunction ||
|
|
OpCode == internal::OpTaskSequenceGetINTEL);
|
|
if (Ty && (!Ty->isTypeVoid() || OpCode == OpFunction ||
|
|
OpCode == internal::OpTaskSequenceGetINTEL))
|
|
setHasType();
|
|
else
|
|
setHasNoType();
|
|
}
|
|
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
SPIRVCapVec CV;
|
|
if (!hasType())
|
|
return CV;
|
|
return Type->getRequiredCapability();
|
|
}
|
|
|
|
std::optional<ExtensionID> getRequiredExtension() const override {
|
|
std::optional<ExtensionID> EV;
|
|
if (!hasType())
|
|
return EV;
|
|
EV = Type->getRequiredExtension();
|
|
assert(Module &&
|
|
(!EV.has_value() || Module->isAllowedToUseExtension(EV.value())));
|
|
return EV;
|
|
}
|
|
|
|
protected:
|
|
void setHasNoType() { Attrib |= SPIRVEA_NOTYPE; }
|
|
void setHasType() { Attrib &= ~SPIRVEA_NOTYPE; }
|
|
|
|
SPIRVType *Type; // Value Type
|
|
};
|
|
|
|
template <spv::Op OC> class SPIRVConstantBase : public SPIRVValue {
|
|
public:
|
|
// Complete constructor for integer constant
|
|
SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
uint64_t TheValue)
|
|
: SPIRVValue(M, 0, OC, TheType, TheId) {
|
|
setWords(&TheValue);
|
|
}
|
|
// Incomplete constructor for AP integer constant
|
|
SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
const llvm::APInt &TheValue);
|
|
// Complete constructor for float constant
|
|
SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
float TheValue)
|
|
: SPIRVValue(M, 0, OC, TheType, TheId) {
|
|
setWords(reinterpret_cast<uint64_t *>(&TheValue));
|
|
}
|
|
// Complete constructor for double constant
|
|
SPIRVConstantBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
double TheValue)
|
|
: SPIRVValue(M, 0, OC, TheType, TheId) {
|
|
setWords(reinterpret_cast<uint64_t *>(&TheValue));
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantBase() : SPIRVValue(OC), NumWords(0) {}
|
|
uint64_t getZExtIntValue() const { return getValue<uint64_t>(); }
|
|
float getFloatValue() const { return getValue<float>(); }
|
|
double getDoubleValue() const { return getValue<double>(); }
|
|
unsigned getNumWords() const { return NumWords; }
|
|
const std::vector<SPIRVWord> &getSPIRVWords() { return Words; }
|
|
|
|
protected:
|
|
constexpr static SPIRVWord FixedWC = 3;
|
|
|
|
// Common method for getting values of size less or equal to 64 bits.
|
|
template <typename T> T getValue() const {
|
|
if (OpCode == OpConstantNull) {
|
|
assert(std::is_arithmetic_v<T> &&
|
|
"OpConstantNull has no defined value for this type");
|
|
return 0;
|
|
}
|
|
constexpr auto ValueSize = static_cast<unsigned>(sizeof(T));
|
|
assert((ValueSize <= 8) && "Incorrect result type of requested value");
|
|
T TheValue{};
|
|
unsigned CopyBytes = std::min(ValueSize, NumWords * SpirvWordSize);
|
|
std::memcpy(&TheValue, Words.data(), CopyBytes);
|
|
return TheValue;
|
|
}
|
|
|
|
void setWords(const uint64_t *TheValue);
|
|
void recalculateWordCount() {
|
|
NumWords =
|
|
(Type->getBitWidth() + SpirvWordBitWidth - 1) / SpirvWordBitWidth;
|
|
WordCount = FixedWC + NumWords;
|
|
}
|
|
void validate() const override {
|
|
SPIRVValue::validate();
|
|
assert(NumWords >= 1 && "Invalid constant size");
|
|
}
|
|
void encode(spv_ostream &O) const override {
|
|
getEncoder(O) << Type << Id;
|
|
for (const auto &Word : Words)
|
|
getEncoder(O) << Word;
|
|
}
|
|
void setWordCount(SPIRVWord WordCount) override {
|
|
SPIRVValue::setWordCount(WordCount);
|
|
NumWords = WordCount - FixedWC;
|
|
}
|
|
void decode(std::istream &I) override {
|
|
getDecoder(I) >> Type >> Id;
|
|
Words.resize(NumWords);
|
|
for (auto &Word : Words)
|
|
getDecoder(I) >> Word;
|
|
}
|
|
|
|
unsigned NumWords;
|
|
|
|
private:
|
|
std::vector<SPIRVWord> Words;
|
|
};
|
|
|
|
using SPIRVConstant = SPIRVConstantBase<OpConstant>;
|
|
using SPIRVSpecConstant = SPIRVConstantBase<OpSpecConstant>;
|
|
|
|
template <Op OC> class SPIRVConstantEmpty : public SPIRVValue {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVConstantEmpty(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVValue(M, 3, OC, TheType, TheId) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantEmpty() : SPIRVValue(OC) {}
|
|
|
|
protected:
|
|
void validate() const override { SPIRVValue::validate(); }
|
|
_SPIRV_DEF_ENCDEC2(Type, Id)
|
|
};
|
|
|
|
template <Op OC> class SPIRVConstantBool : public SPIRVConstantEmpty<OC> {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVConstantBool(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVConstantEmpty<OC>(M, TheType, TheId) {}
|
|
// Incomplete constructor
|
|
SPIRVConstantBool() {}
|
|
|
|
protected:
|
|
void validate() const override {
|
|
SPIRVConstantEmpty<OC>::validate();
|
|
assert(this->Type->isTypeBool() && "Invalid type");
|
|
}
|
|
};
|
|
|
|
typedef SPIRVConstantBool<OpConstantTrue> SPIRVConstantTrue;
|
|
typedef SPIRVConstantBool<OpConstantFalse> SPIRVConstantFalse;
|
|
typedef SPIRVConstantBool<OpSpecConstantTrue> SPIRVSpecConstantTrue;
|
|
typedef SPIRVConstantBool<OpSpecConstantFalse> SPIRVSpecConstantFalse;
|
|
|
|
class SPIRVConstantNull : public SPIRVConstantEmpty<OpConstantNull> {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVConstantNull(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVConstantEmpty(M, TheType, TheId) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantNull() {}
|
|
|
|
protected:
|
|
void validate() const override {
|
|
SPIRVConstantEmpty::validate();
|
|
assert((Type->isTypeBool() || Type->isTypeInt() || Type->isTypeFloat() ||
|
|
Type->isTypeComposite() || Type->isTypeOpaque() ||
|
|
Type->isTypeEvent() || Type->isTypePointer() ||
|
|
Type->isTypeReserveId() || Type->isTypeDeviceEvent() ||
|
|
(Type->isTypeSubgroupAvcINTEL() &&
|
|
!Type->isTypeSubgroupAvcMceINTEL())) &&
|
|
"Invalid type");
|
|
}
|
|
};
|
|
|
|
class SPIRVUndef : public SPIRVConstantEmpty<OpUndef> {
|
|
public:
|
|
// Complete constructor
|
|
SPIRVUndef(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVConstantEmpty(M, TheType, TheId) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVUndef() {}
|
|
|
|
protected:
|
|
void validate() const override { SPIRVConstantEmpty::validate(); }
|
|
};
|
|
|
|
class SPIRVPoisonKHR : public SPIRVConstantEmpty<OpPoisonKHR> {
|
|
public:
|
|
SPIRVPoisonKHR(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId)
|
|
: SPIRVConstantEmpty(M, TheType, TheId) {
|
|
validate();
|
|
}
|
|
SPIRVPoisonKHR() {}
|
|
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
return getVec(CapabilityPoisonFreezeKHR);
|
|
}
|
|
|
|
std::optional<ExtensionID> getRequiredExtension() const override {
|
|
return ExtensionID::SPV_KHR_poison_freeze;
|
|
}
|
|
|
|
protected:
|
|
void validate() const override { SPIRVConstantEmpty::validate(); }
|
|
};
|
|
|
|
template <spv::Op OC> class SPIRVConstantCompositeBase : public SPIRVValue {
|
|
public:
|
|
// There are always 3 words in this instruction except constituents:
|
|
// 1) WordCount + OpCode
|
|
// 2) Result type
|
|
// 3) Result Id
|
|
constexpr static SPIRVWord FixedWC = 3;
|
|
using ContinuedInstType = typename InstToContinued<OC>::Type;
|
|
// Complete constructor for composite constant
|
|
SPIRVConstantCompositeBase(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
const std::vector<SPIRVValue *> TheElements)
|
|
: SPIRVValue(M, TheElements.size() + FixedWC, OC, TheType, TheId) {
|
|
Elements = getIds(TheElements);
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantCompositeBase() : SPIRVValue(OC) {}
|
|
std::vector<SPIRVValue *> getElements() const { return getValues(Elements); }
|
|
|
|
// TODO: Should we attach operands of continued instructions as well?
|
|
std::vector<SPIRVEntry *> getNonLiteralOperands() const override {
|
|
std::vector<SPIRVValue *> Elements = getElements();
|
|
return std::vector<SPIRVEntry *>(Elements.begin(), Elements.end());
|
|
}
|
|
|
|
std::vector<ContinuedInstType> getContinuedInstructions() {
|
|
return ContinuedInstructions;
|
|
}
|
|
|
|
void addContinuedInstruction(ContinuedInstType Inst) {
|
|
ContinuedInstructions.push_back(Inst);
|
|
}
|
|
|
|
void encodeChildren(spv_ostream &O) const override {
|
|
O << SPIRVNL();
|
|
for (auto &I : ContinuedInstructions)
|
|
O << *I;
|
|
}
|
|
|
|
protected:
|
|
void validate() const override {
|
|
SPIRVValue::validate();
|
|
for (auto &I : Elements)
|
|
getValue(I)->validate();
|
|
}
|
|
|
|
void setWordCount(SPIRVWord WordCount) override {
|
|
SPIRVEntry::setWordCount(WordCount);
|
|
SPIRVCK(WordCount >= FixedWC, InvalidWordCount, "");
|
|
Elements.resize(WordCount - FixedWC);
|
|
}
|
|
|
|
void encode(spv_ostream &O) const override {
|
|
getEncoder(O) << Type << Id << Elements;
|
|
}
|
|
|
|
void decode(std::istream &I) override {
|
|
SPIRVDecoder Decoder = getDecoder(I);
|
|
Decoder >> Type >> Id >> Elements;
|
|
|
|
for (SPIRVEntry *E : Decoder.getContinuedInstructions(ContinuedOpCode)) {
|
|
addContinuedInstruction(static_cast<ContinuedInstType>(E));
|
|
}
|
|
}
|
|
|
|
std::vector<SPIRVId> Elements;
|
|
std::vector<ContinuedInstType> ContinuedInstructions;
|
|
const spv::Op ContinuedOpCode = InstToContinued<OC>::OpCode;
|
|
};
|
|
|
|
using SPIRVConstantComposite = SPIRVConstantCompositeBase<OpConstantComposite>;
|
|
using SPIRVSpecConstantComposite =
|
|
SPIRVConstantCompositeBase<OpSpecConstantComposite>;
|
|
|
|
class SPIRVConstantSampler : public SPIRVValue {
|
|
public:
|
|
const static Op OC = OpConstantSampler;
|
|
const static SPIRVWord WC = 6;
|
|
// Complete constructor
|
|
SPIRVConstantSampler(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
SPIRVWord TheAddrMode, SPIRVWord TheNormalized,
|
|
SPIRVWord TheFilterMode)
|
|
: SPIRVValue(M, WC, OC, TheType, TheId), AddrMode(TheAddrMode),
|
|
Normalized(TheNormalized), FilterMode(TheFilterMode) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantSampler()
|
|
: SPIRVValue(OC), AddrMode(SPIRVSAM_Invalid), Normalized(SPIRVWORD_MAX),
|
|
FilterMode(SPIRVSFM_Invalid) {}
|
|
|
|
SPIRVWord getAddrMode() const { return AddrMode; }
|
|
|
|
SPIRVWord getFilterMode() const { return FilterMode; }
|
|
|
|
SPIRVWord getNormalized() const { return Normalized; }
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
return getVec(CapabilityLiteralSampler);
|
|
}
|
|
|
|
protected:
|
|
SPIRVWord AddrMode;
|
|
SPIRVWord Normalized;
|
|
SPIRVWord FilterMode;
|
|
void validate() const override {
|
|
SPIRVValue::validate();
|
|
assert(OpCode == OC);
|
|
assert(WordCount == WC);
|
|
assert(Type->isTypeSampler());
|
|
}
|
|
_SPIRV_DEF_ENCDEC5(Type, Id, AddrMode, Normalized, FilterMode)
|
|
};
|
|
|
|
class SPIRVConstantPipeStorage : public SPIRVValue {
|
|
public:
|
|
const static Op OC = OpConstantPipeStorage;
|
|
const static SPIRVWord WC = 6;
|
|
// Complete constructor
|
|
SPIRVConstantPipeStorage(SPIRVModule *M, SPIRVType *TheType, SPIRVId TheId,
|
|
SPIRVWord ThePacketSize, SPIRVWord ThePacketAlign,
|
|
SPIRVWord TheCapacity)
|
|
: SPIRVValue(M, WC, OC, TheType, TheId), PacketSize(ThePacketSize),
|
|
PacketAlign(ThePacketAlign), Capacity(TheCapacity) {
|
|
validate();
|
|
}
|
|
// Incomplete constructor
|
|
SPIRVConstantPipeStorage()
|
|
: SPIRVValue(OC), PacketSize(0), PacketAlign(0), Capacity(0) {}
|
|
|
|
SPIRVWord getPacketSize() const { return PacketSize; }
|
|
|
|
SPIRVWord getPacketAlign() const { return PacketAlign; }
|
|
|
|
SPIRVWord getCapacity() const { return Capacity; }
|
|
SPIRVCapVec getRequiredCapability() const override {
|
|
return getVec(CapabilityPipes, CapabilityPipeStorage);
|
|
}
|
|
|
|
protected:
|
|
SPIRVWord PacketSize;
|
|
SPIRVWord PacketAlign;
|
|
SPIRVWord Capacity;
|
|
void validate() const override {
|
|
SPIRVValue::validate();
|
|
assert(OpCode == OC);
|
|
assert(WordCount == WC);
|
|
assert(Type->isTypePipeStorage());
|
|
}
|
|
_SPIRV_DEF_ENCDEC5(Type, Id, PacketSize, PacketAlign, Capacity)
|
|
};
|
|
|
|
class SPIRVForward : public SPIRVValue, public SPIRVComponentExecutionModes {
|
|
public:
|
|
const static Op OC = internal::OpForward;
|
|
// Complete constructor
|
|
SPIRVForward(SPIRVModule *TheModule, SPIRVType *TheTy, SPIRVId TheId)
|
|
: SPIRVValue(TheModule, 0, OC, TheId) {
|
|
if (TheTy)
|
|
setType(TheTy);
|
|
}
|
|
SPIRVForward() : SPIRVValue(OC) { assert(0 && "should never be called"); }
|
|
_SPIRV_DEF_ENCDEC1(Id)
|
|
friend class SPIRVFunction;
|
|
|
|
protected:
|
|
void validate() const override {}
|
|
};
|
|
|
|
} // namespace SPIRV
|
|
|
|
#endif // SPIRV_LIBSPIRV_SPIRVVALUE_H
|