Skip to content

Commit ab78ffb

Browse files
vmaksimojsji
authored andcommitted
SPV_KHR_untyped_pointers - implement OpTypeUntypedPointerKHR (#2687)
This is the first part of the extension implementation. Introducing untyped pointer type. Spec: https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_untyped_pointers.html Original commit: KhronosGroup/SPIRV-LLVM-Translator@7dacb7cdedc9c01
1 parent 41f496b commit ab78ffb

File tree

19 files changed

+372
-55
lines changed

19 files changed

+372
-55
lines changed

llvm-spirv/include/LLVMSPIRVExtensions.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ EXT(SPV_KHR_subgroup_rotate)
1717
EXT(SPV_KHR_non_semantic_info)
1818
EXT(SPV_KHR_shader_clock)
1919
EXT(SPV_KHR_cooperative_matrix)
20+
EXT(SPV_KHR_untyped_pointers)
2021
EXT(SPV_INTEL_subgroups)
2122
EXT(SPV_INTEL_media_block_io)
2223
EXT(SPV_INTEL_device_side_avc_motion_estimation)

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ Type *SPIRVToLLVM::transType(SPIRVType *T, bool UseTPT) {
357357
return TypedPointerType::get(ElementTy, AS);
358358
return mapType(T, PointerType::get(ElementTy, AS));
359359
}
360+
case OpTypeUntypedPointerKHR: {
361+
const unsigned AS =
362+
SPIRSPIRVAddrSpaceMap::rmap(T->getPointerStorageClass());
363+
return mapType(T, PointerType::get(*Context, AS));
364+
}
360365
case OpTypeVector:
361366
return mapType(T,
362367
FixedVectorType::get(transType(T->getVectorComponentType()),
@@ -560,6 +565,8 @@ std::string SPIRVToLLVM::transTypeToOCLTypeName(SPIRVType *T, bool IsSigned) {
560565
}
561566
return transTypeToOCLTypeName(ET) + "*";
562567
}
568+
case OpTypeUntypedPointerKHR:
569+
return "int*";
563570
case OpTypeVector:
564571
return transTypeToOCLTypeName(T->getVectorComponentType()) +
565572
T->getVectorComponentCount();

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@ SPIRVType *LLVMToSPIRVBase::transType(Type *T) {
417417
// A pointer to image or pipe type in LLVM is translated to a SPIRV
418418
// (non-pointer) image or pipe type.
419419
if (T->isPointerTy()) {
420-
auto *ET = Type::getInt8Ty(T->getContext());
421420
auto AddrSpc = T->getPointerAddressSpace();
421+
auto *ET = Type::getInt8Ty(T->getContext());
422422
return transPointerType(ET, AddrSpc);
423423
}
424424

@@ -720,7 +720,6 @@ SPIRVType *LLVMToSPIRVBase::transPointerType(Type *ET, unsigned AddrSpc) {
720720
transType(ET)));
721721
}
722722
} else {
723-
SPIRVType *ElementType = transType(ET);
724723
// ET, as a recursive type, may contain exactly the same pointer T, so it
725724
// may happen that after translation of ET we already have translated T,
726725
// added the translated pointer to the SPIR-V module and mapped T to this
@@ -729,7 +728,17 @@ SPIRVType *LLVMToSPIRVBase::transPointerType(Type *ET, unsigned AddrSpc) {
729728
if (Loc != PointeeTypeMap.end()) {
730729
return Loc->second;
731730
}
732-
SPIRVType *TranslatedTy = transPointerType(ElementType, AddrSpc);
731+
732+
SPIRVType *ElementType = nullptr;
733+
SPIRVType *TranslatedTy = nullptr;
734+
if (ET->isPointerTy() &&
735+
BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers)) {
736+
TranslatedTy = BM->addUntypedPointerKHRType(
737+
SPIRSPIRVAddrSpaceMap::map(static_cast<SPIRAddressSpace>(AddrSpc)));
738+
} else {
739+
ElementType = transType(ET);
740+
TranslatedTy = transPointerType(ElementType, AddrSpc);
741+
}
733742
PointeeTypeMap[TypeKey] = TranslatedTy;
734743
return TranslatedTy;
735744
}
@@ -744,8 +753,16 @@ SPIRVType *LLVMToSPIRVBase::transPointerType(SPIRVType *ET, unsigned AddrSpc) {
744753
if (Loc != PointeeTypeMap.end())
745754
return Loc->second;
746755

747-
SPIRVType *TranslatedTy = BM->addPointerType(
748-
SPIRSPIRVAddrSpaceMap::map(static_cast<SPIRAddressSpace>(AddrSpc)), ET);
756+
SPIRVType *TranslatedTy = nullptr;
757+
if (BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers) &&
758+
!(ET->isTypeArray() || ET->isTypeVector() || ET->isTypeImage() ||
759+
ET->isTypeSampler() || ET->isTypePipe())) {
760+
TranslatedTy = BM->addUntypedPointerKHRType(
761+
SPIRSPIRVAddrSpaceMap::map(static_cast<SPIRAddressSpace>(AddrSpc)));
762+
} else {
763+
TranslatedTy = BM->addPointerType(
764+
SPIRSPIRVAddrSpaceMap::map(static_cast<SPIRAddressSpace>(AddrSpc)), ET);
765+
}
749766
PointeeTypeMap[TypeKey] = TranslatedTy;
750767
return TranslatedTy;
751768
}
@@ -2184,8 +2201,13 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
21842201
MemoryAccessNoAliasINTELMaskMask);
21852202
if (MemoryAccess.front() == 0)
21862203
MemoryAccess.clear();
2187-
return mapValue(V, BM->addLoadInst(transValue(LD->getPointerOperand(), BB),
2188-
MemoryAccess, BB));
2204+
return mapValue(
2205+
V,
2206+
BM->addLoadInst(
2207+
transValue(LD->getPointerOperand(), BB), MemoryAccess, BB,
2208+
BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers)
2209+
? transType(LD->getType())
2210+
: nullptr));
21892211
}
21902212

21912213
if (BinaryOperator *B = dyn_cast<BinaryOperator>(V)) {
@@ -2395,14 +2417,17 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
23952417

23962418
if (auto *Phi = dyn_cast<PHINode>(V)) {
23972419
std::vector<SPIRVValue *> IncomingPairs;
2420+
SPIRVType *Ty = transScavengedType(Phi);
23982421

23992422
for (size_t I = 0, E = Phi->getNumIncomingValues(); I != E; ++I) {
2400-
IncomingPairs.push_back(transValue(Phi->getIncomingValue(I), BB, true,
2401-
FuncTransMode::Pointer));
2423+
SPIRVValue *Val = transValue(Phi->getIncomingValue(I), BB, true,
2424+
FuncTransMode::Pointer);
2425+
if (Val->getType() != Ty)
2426+
Val = BM->addUnaryInst(OpBitcast, Ty, Val, BB);
2427+
IncomingPairs.push_back(Val);
24022428
IncomingPairs.push_back(transValue(Phi->getIncomingBlock(I), nullptr));
24032429
}
2404-
return mapValue(V,
2405-
BM->addPhiInst(transScavengedType(Phi), IncomingPairs, BB));
2430+
return mapValue(V, BM->addPhiInst(Ty, IncomingPairs, BB));
24062431
}
24072432

24082433
if (auto *Ext = dyn_cast<ExtractValueInst>(V)) {
@@ -6659,9 +6684,12 @@ LLVMToSPIRVBase::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
66596684
assert((Pointee == Args[I] || !isa<Function>(Pointee)) &&
66606685
"Illegal use of a function pointer type");
66616686
}
6662-
SPArgs.push_back(SPI->isOperandLiteral(I)
6663-
? cast<ConstantInt>(Args[I])->getZExtValue()
6664-
: transValue(Args[I], BB)->getId());
6687+
if (!SPI->isOperandLiteral(I)) {
6688+
SPIRVValue *Val = transValue(Args[I], BB);
6689+
SPArgs.push_back(Val->getId());
6690+
} else {
6691+
SPArgs.push_back(cast<ConstantInt>(Args[I])->getZExtValue());
6692+
}
66656693
}
66666694
BM->addInstTemplate(SPI, SPArgs, BB, SPRetTy);
66676695
if (!SPRetTy || !SPRetTy->isTypeStruct())

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,15 @@ class SPIRVStore : public SPIRVInstruction, public SPIRVMemoryAccess {
568568
SPIRVInstruction::validate();
569569
if (getSrc()->isForward() || getDst()->isForward())
570570
return;
571-
assert(getValueType(PtrId)->getPointerElementType() ==
572-
getValueType(ValId) &&
573-
"Inconsistent operand types");
571+
assert(
572+
(getValueType(PtrId)
573+
->getPointerElementType()
574+
->isTypeUntypedPointerKHR() ||
575+
// TODO: This check should be removed once we support untyped
576+
// variables.
577+
getValueType(ValId)->isTypeUntypedPointerKHR() ||
578+
getValueType(PtrId)->getPointerElementType() == getValueType(ValId)) &&
579+
"Inconsistent operand types");
574580
}
575581

576582
private:
@@ -585,11 +591,12 @@ class SPIRVLoad : public SPIRVInstruction, public SPIRVMemoryAccess {
585591
// Complete constructor
586592
SPIRVLoad(SPIRVId TheId, SPIRVId PointerId,
587593
const std::vector<SPIRVWord> &TheMemoryAccess,
588-
SPIRVBasicBlock *TheBB)
594+
SPIRVBasicBlock *TheBB, SPIRVType *TheType = nullptr)
589595
: SPIRVInstruction(
590596
FixedWords + TheMemoryAccess.size(), OpLoad,
591-
TheBB->getValueType(PointerId)->getPointerElementType(), TheId,
592-
TheBB),
597+
TheType ? TheType
598+
: TheBB->getValueType(PointerId)->getPointerElementType(),
599+
TheId, TheBB),
593600
SPIRVMemoryAccess(TheMemoryAccess), PtrId(PointerId),
594601
MemoryAccess(TheMemoryAccess) {
595602
validate();
@@ -619,6 +626,12 @@ class SPIRVLoad : public SPIRVInstruction, public SPIRVMemoryAccess {
619626
void validate() const override {
620627
SPIRVInstruction::validate();
621628
assert((getValue(PtrId)->isForward() ||
629+
getValueType(PtrId)
630+
->getPointerElementType()
631+
->isTypeUntypedPointerKHR() ||
632+
// TODO: This check should be removed once we support untyped
633+
// variables.
634+
Type->isTypeUntypedPointerKHR() ||
622635
Type == getValueType(PtrId)->getPointerElementType()) &&
623636
"Inconsistent types");
624637
}
@@ -2001,7 +2014,8 @@ class SPIRVCompositeExtractBase : public SPIRVInstTemplateBase {
20012014
(void)Composite;
20022015
assert(getValueType(Composite)->isTypeArray() ||
20032016
getValueType(Composite)->isTypeStruct() ||
2004-
getValueType(Composite)->isTypeVector());
2017+
getValueType(Composite)->isTypeVector() ||
2018+
getValueType(Composite)->isTypeUntypedPointerKHR());
20052019
}
20062020
};
20072021

@@ -2027,7 +2041,8 @@ class SPIRVCompositeInsertBase : public SPIRVInstTemplateBase {
20272041
(void)Composite;
20282042
assert(getValueType(Composite)->isTypeArray() ||
20292043
getValueType(Composite)->isTypeStruct() ||
2030-
getValueType(Composite)->isTypeVector());
2044+
getValueType(Composite)->isTypeVector() ||
2045+
getValueType(Composite)->isTypeUntypedPointerKHR());
20312046
assert(Type == getValueType(Composite));
20322047
}
20332048
};
@@ -2374,7 +2389,8 @@ template <Op OC> class SPIRVLifetime : public SPIRVInstruction {
23742389
// Signedness of 1, its sign bit cannot be set.
23752390
if (!(ObjType->getPointerElementType()->isTypeVoid() ||
23762391
// (void *) is i8* in LLVM IR
2377-
ObjType->getPointerElementType()->isTypeInt(8)) ||
2392+
ObjType->getPointerElementType()->isTypeInt(8) ||
2393+
ObjType->getPointerElementType()->isTypeUntypedPointerKHR()) ||
23782394
!Module->hasCapability(CapabilityAddresses))
23792395
assert(Size == 0 && "Size must be 0");
23802396
}

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ class SPIRVModuleImpl : public SPIRVModule {
252252
SPIRVTypeInt *addIntegerType(unsigned BitWidth) override;
253253
SPIRVTypeOpaque *addOpaqueType(const std::string &) override;
254254
SPIRVTypePointer *addPointerType(SPIRVStorageClassKind, SPIRVType *) override;
255+
SPIRVTypeUntypedPointerKHR *
256+
addUntypedPointerKHRType(SPIRVStorageClassKind) override;
255257
SPIRVTypeImage *addImageType(SPIRVType *,
256258
const SPIRVTypeImageDescriptor &) override;
257259
SPIRVTypeImage *addImageType(SPIRVType *, const SPIRVTypeImageDescriptor &,
@@ -353,7 +355,7 @@ class SPIRVModuleImpl : public SPIRVModule {
353355
SPIRVInstruction *addCmpInst(Op, SPIRVType *, SPIRVValue *, SPIRVValue *,
354356
SPIRVBasicBlock *) override;
355357
SPIRVInstruction *addLoadInst(SPIRVValue *, const std::vector<SPIRVWord> &,
356-
SPIRVBasicBlock *) override;
358+
SPIRVBasicBlock *, SPIRVType *) override;
357359
SPIRVInstruction *addPhiInst(SPIRVType *, std::vector<SPIRVValue *>,
358360
SPIRVBasicBlock *) override;
359361
SPIRVInstruction *addCompositeConstructInst(SPIRVType *,
@@ -563,6 +565,8 @@ class SPIRVModuleImpl : public SPIRVModule {
563565
SPIRVUnknownStructFieldMap UnknownStructFieldMap;
564566
SPIRVTypeBool *BoolTy;
565567
SPIRVTypeVoid *VoidTy;
568+
SmallDenseMap<SPIRVStorageClassKind, SPIRVTypeUntypedPointerKHR *>
569+
UntypedPtrTyMap;
566570
SmallDenseMap<unsigned, SPIRVTypeInt *, 4> IntTypeMap;
567571
SmallDenseMap<unsigned, SPIRVTypeFloat *, 4> FloatTypeMap;
568572
SmallDenseMap<std::pair<unsigned, SPIRVType *>, SPIRVTypePointer *, 4>
@@ -1014,6 +1018,17 @@ SPIRVModuleImpl::addPointerType(SPIRVStorageClassKind StorageClass,
10141018
return addType(Ty);
10151019
}
10161020

1021+
SPIRVTypeUntypedPointerKHR *
1022+
SPIRVModuleImpl::addUntypedPointerKHRType(SPIRVStorageClassKind StorageClass) {
1023+
auto Loc = UntypedPtrTyMap.find(StorageClass);
1024+
if (Loc != UntypedPtrTyMap.end())
1025+
return Loc->second;
1026+
1027+
auto *Ty = new SPIRVTypeUntypedPointerKHR(this, getId(), StorageClass);
1028+
UntypedPtrTyMap[StorageClass] = Ty;
1029+
return addType(Ty);
1030+
}
1031+
10171032
SPIRVTypeFunction *SPIRVModuleImpl::addFunctionType(
10181033
SPIRVType *ReturnType, const std::vector<SPIRVType *> &ParameterTypes) {
10191034
return addType(
@@ -1430,9 +1445,10 @@ SPIRVModuleImpl::addInstruction(SPIRVInstruction *Inst, SPIRVBasicBlock *BB,
14301445
SPIRVInstruction *
14311446
SPIRVModuleImpl::addLoadInst(SPIRVValue *Source,
14321447
const std::vector<SPIRVWord> &TheMemoryAccess,
1433-
SPIRVBasicBlock *BB) {
1448+
SPIRVBasicBlock *BB, SPIRVType *TheType) {
14341449
return addInstruction(
1435-
new SPIRVLoad(getId(), Source->getId(), TheMemoryAccess, BB), BB);
1450+
new SPIRVLoad(getId(), Source->getId(), TheMemoryAccess, BB, TheType),
1451+
BB);
14361452
}
14371453

14381454
SPIRVInstruction *
@@ -1925,11 +1941,13 @@ class TopologicalSort {
19251941
// We've found a recursive data type, e.g. a structure having a member
19261942
// which is a pointer to the same structure.
19271943
State = Unvisited; // Forget about it
1928-
if (E->getOpCode() == OpTypePointer) {
1944+
if (E->getOpCode() == OpTypePointer ||
1945+
E->getOpCode() == OpTypeUntypedPointerKHR) {
19291946
// If we have a pointer in the recursive chain, we can break the
19301947
// cyclic dependency by inserting a forward declaration of that
19311948
// pointer.
1932-
SPIRVTypePointer *Ptr = static_cast<SPIRVTypePointer *>(E);
1949+
SPIRVTypePointerBase<> *Ptr =
1950+
static_cast<SPIRVTypePointerBase<> *>(E);
19331951
SPIRVModule *BM = E->getModule();
19341952
ForwardPointerSet.insert(BM->add(new SPIRVTypeForwardPointer(
19351953
BM, Ptr->getId(), Ptr->getPointerStorageClass())));

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class SPIRVTypeFunction;
7171
class SPIRVTypeInt;
7272
class SPIRVTypeOpaque;
7373
class SPIRVTypePointer;
74+
class SPIRVTypeUntypedPointerKHR;
7475
class SPIRVTypeImage;
7576
class SPIRVTypeSampler;
7677
class SPIRVTypeSampledImage;
@@ -257,6 +258,8 @@ class SPIRVModule {
257258
virtual SPIRVTypeOpaque *addOpaqueType(const std::string &) = 0;
258259
virtual SPIRVTypePointer *addPointerType(SPIRVStorageClassKind,
259260
SPIRVType *) = 0;
261+
virtual SPIRVTypeUntypedPointerKHR *
262+
addUntypedPointerKHRType(SPIRVStorageClassKind) = 0;
260263
virtual SPIRVTypeStruct *openStructType(unsigned, const std::string &) = 0;
261264
virtual SPIRVEntry *addTypeStructContinuedINTEL(unsigned NumMembers) = 0;
262265
virtual void closeStructType(SPIRVTypeStruct *, bool) = 0;
@@ -396,7 +399,8 @@ class SPIRVModule {
396399
SPIRVBasicBlock *BB, SPIRVType *Ty) = 0;
397400
virtual SPIRVInstruction *addLoadInst(SPIRVValue *,
398401
const std::vector<SPIRVWord> &,
399-
SPIRVBasicBlock *) = 0;
402+
SPIRVBasicBlock *,
403+
SPIRVType *TheType = nullptr) = 0;
400404
virtual SPIRVInstruction *addLifetimeInst(Op OC, SPIRVValue *Object,
401405
SPIRVWord Size,
402406
SPIRVBasicBlock *BB) = 0;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ template <> inline void SPIRVMap<Capability, std::string>::init() {
478478
add(CapabilityRoundingModeRTZ, "RoundingModeRTZ");
479479
add(CapabilityRayQueryProvisionalKHR, "RayQueryProvisionalKHR");
480480
add(CapabilityRayQueryKHR, "RayQueryKHR");
481+
add(CapabilityUntypedPointersKHR, "UntypedPointersKHR");
481482
add(CapabilityRayTraversalPrimitiveCullingKHR,
482483
"RayTraversalPrimitiveCullingKHR");
483484
add(CapabilityRayTracingKHR, "RayTracingKHR");

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ inline bool isTypeOpCode(Op OpCode) {
227227
OC == internal::OpTypeJointMatrixINTEL ||
228228
OC == internal::OpTypeJointMatrixINTELv2 ||
229229
OC == OpTypeCooperativeMatrixKHR ||
230-
OC == internal::OpTypeTaskSequenceINTEL;
230+
OC == internal::OpTypeTaskSequenceINTEL ||
231+
OC == OpTypeUntypedPointerKHR;
231232
}
232233

233234
inline bool isSpecConstantOpCode(Op OpCode) {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,11 @@ _SPIRV_OP(GroupNonUniformBitwiseXor, 361)
329329
_SPIRV_OP(GroupNonUniformLogicalAnd, 362)
330330
_SPIRV_OP(GroupNonUniformLogicalOr, 363)
331331
_SPIRV_OP(GroupNonUniformLogicalXor, 364)
332-
_SPIRV_OP(PtrEqual, 401)
333-
_SPIRV_OP(PtrNotEqual, 402)
334-
_SPIRV_OP(PtrDiff, 403)
335332
_SPIRV_OP(CopyLogical, 400)
336333
_SPIRV_OP(PtrEqual, 401)
337334
_SPIRV_OP(PtrNotEqual, 402)
338335
_SPIRV_OP(PtrDiff, 403)
336+
_SPIRV_OP(TypeUntypedPointerKHR, 4417)
339337
_SPIRV_OP(GroupNonUniformRotateKHR, 4431)
340338
_SPIRV_OP(SDotKHR, 4450)
341339
_SPIRV_OP(UDotKHR, 4451)

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVType.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,16 @@ SPIRVType *SPIRVType::getFunctionReturnType() const {
8686
}
8787

8888
SPIRVType *SPIRVType::getPointerElementType() const {
89-
assert(OpCode == OpTypePointer && "Not a pointer type");
89+
assert((OpCode == OpTypePointer || OpCode == OpTypeUntypedPointerKHR) &&
90+
"Not a pointer type");
91+
if (OpCode == OpTypeUntypedPointerKHR)
92+
return const_cast<SPIRVType *>(this);
9093
return static_cast<const SPIRVTypePointer *>(this)->getElementType();
9194
}
9295

9396
SPIRVStorageClassKind SPIRVType::getPointerStorageClass() const {
94-
assert(OpCode == OpTypePointer && "Not a pointer type");
97+
assert((OpCode == OpTypePointer || OpCode == OpTypeUntypedPointerKHR) &&
98+
"Not a pointer type");
9599
return static_cast<const SPIRVTypePointer *>(this)->getStorageClass();
96100
}
97101

@@ -183,7 +187,13 @@ bool SPIRVType::isTypeInt(unsigned Bits) const {
183187
return isType<SPIRVTypeInt>(this, Bits);
184188
}
185189

186-
bool SPIRVType::isTypePointer() const { return OpCode == OpTypePointer; }
190+
bool SPIRVType::isTypePointer() const {
191+
return OpCode == OpTypePointer || OpCode == OpTypeUntypedPointerKHR;
192+
}
193+
194+
bool SPIRVType::isTypeUntypedPointerKHR() const {
195+
return OpCode == OpTypeUntypedPointerKHR;
196+
}
187197

188198
bool SPIRVType::isTypeOpaque() const { return OpCode == OpTypeOpaque; }
189199

0 commit comments

Comments
 (0)