diff options
author | Cassandra Beckley <beckl.ds@gmail.com> | 2025-05-27 08:40:54 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-27 11:40:54 -0400 |
commit | 5a4571133af78e365e6e7b271688b9ceaa653e67 (patch) | |
tree | 5018fb04b5ca4301262735fb16d7d27a20414799 /clang/lib/CodeGen | |
parent | 58f80536d3ee1a9ca3e8aa62da92d33d4bc9cc8c (diff) | |
download | llvm-5a4571133af78e365e6e7b271688b9ceaa653e67.zip llvm-5a4571133af78e365e6e7b271688b9ceaa653e67.tar.gz llvm-5a4571133af78e365e6e7b271688b9ceaa653e67.tar.bz2 |
[HLSL] Implement `SpirvType` and `SpirvOpaqueType` (#134034)
This implements the design proposed by [Representing SpirvType in
Clang's Type System](https://github.com/llvm/wg-hlsl/pull/181). It
creates `HLSLInlineSpirvType` as a new `Type` subclass, and
`__hlsl_spirv_type` as a new builtin type template to create such a
type.
This new type is lowered to the `spirv.Type` target extension type, as
described in [Target Extension Types for Inline SPIR-V and Decorated
Types](https://github.com/llvm/wg-hlsl/blob/main/proposals/0017-inline-spirv-and-decorated-types.md).
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/Targets/SPIR.cpp | 87 |
6 files changed, 104 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 21896c9..d5662b1 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -3638,6 +3638,12 @@ llvm::DIType *CGDebugInfo::CreateType(const HLSLAttributedResourceType *Ty, return getOrCreateType(Ty->getWrappedType(), U); } +llvm::DIType *CGDebugInfo::CreateType(const HLSLInlineSpirvType *Ty, + llvm::DIFile *U) { + // Debug information unneeded. + return nullptr; +} + llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); @@ -3991,6 +3997,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateType(cast<TemplateSpecializationType>(Ty), Unit); case Type::HLSLAttributedResource: return CreateType(cast<HLSLAttributedResourceType>(Ty), Unit); + case Type::HLSLInlineSpirv: + return CreateType(cast<HLSLInlineSpirvType>(Ty), Unit); case Type::CountAttributed: case Type::Auto: diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 79d031a..ec27fb0 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -210,6 +210,7 @@ private: llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const HLSLAttributedResourceType *Ty, llvm::DIFile *F); + llvm::DIType *CreateType(const HLSLInlineSpirvType *Ty, llvm::DIFile *F); /// Get structure or union type. llvm::DIType *CreateType(const RecordType *Tyg); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0356952..e235756 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -283,6 +283,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::Pipe: case Type::BitInt: case Type::HLSLAttributedResource: + case Type::HLSLInlineSpirv: return TEK_Scalar; // Complexes. @@ -2473,6 +2474,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::ObjCInterface: case Type::ObjCObjectPointer: case Type::BitInt: + case Type::HLSLInlineSpirv: llvm_unreachable("type class is never variably-modified!"); case Type::Elaborated: diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 843733b..36c5f2b 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -765,6 +765,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { break; } case Type::HLSLAttributedResource: + case Type::HLSLInlineSpirv: ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty); break; } @@ -877,6 +878,10 @@ bool CodeGenTypes::isZeroInitializable(QualType T) { if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) return getCXXABI().isZeroInitializable(MPT); + // HLSL Inline SPIR-V types are non-zero-initializable. + if (T->getAs<HLSLInlineSpirvType>()) + return false; + // Everything else is okay. return true; } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 5018a6b..e811474 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3962,6 +3962,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty, break; case Type::HLSLAttributedResource: + case Type::HLSLInlineSpirv: llvm_unreachable("HLSL doesn't support virtual functions"); } @@ -4237,6 +4238,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( break; case Type::HLSLAttributedResource: + case Type::HLSLInlineSpirv: llvm_unreachable("HLSL doesn't support RTTI"); } diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index f35c124..cb190b3 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -377,14 +377,99 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM, return nullptr; } +// Gets a spirv.IntegralConstant or spirv.Literal. If IntegralType is present, +// returns an IntegralConstant, otherwise returns a Literal. +static llvm::Type *getInlineSpirvConstant(CodeGenModule &CGM, + llvm::Type *IntegralType, + llvm::APInt Value) { + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + + // Convert the APInt value to an array of uint32_t words + llvm::SmallVector<uint32_t> Words; + + while (Value.ugt(0)) { + uint32_t Word = Value.trunc(32).getZExtValue(); + Value.lshrInPlace(32); + + Words.push_back(Word); + } + if (Words.size() == 0) + Words.push_back(0); + + if (IntegralType) + return llvm::TargetExtType::get(Ctx, "spirv.IntegralConstant", + {IntegralType}, Words); + return llvm::TargetExtType::get(Ctx, "spirv.Literal", {}, Words); +} + +static llvm::Type *getInlineSpirvType(CodeGenModule &CGM, + const HLSLInlineSpirvType *SpirvType) { + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + + llvm::SmallVector<llvm::Type *> Operands; + + for (auto &Operand : SpirvType->getOperands()) { + using SpirvOperandKind = SpirvOperand::SpirvOperandKind; + + llvm::Type *Result = nullptr; + switch (Operand.getKind()) { + case SpirvOperandKind::ConstantId: { + llvm::Type *IntegralType = + CGM.getTypes().ConvertType(Operand.getResultType()); + llvm::APInt Value = Operand.getValue(); + + Result = getInlineSpirvConstant(CGM, IntegralType, Value); + break; + } + case SpirvOperandKind::Literal: { + llvm::APInt Value = Operand.getValue(); + Result = getInlineSpirvConstant(CGM, nullptr, Value); + break; + } + case SpirvOperandKind::TypeId: { + QualType TypeOperand = Operand.getResultType(); + if (auto *RT = TypeOperand->getAs<RecordType>()) { + auto *RD = RT->getDecl(); + assert(RD->isCompleteDefinition() && + "Type completion should have been required in Sema"); + + const FieldDecl *HandleField = RD->findFirstNamedDataMember(); + if (HandleField) { + QualType ResourceType = HandleField->getType(); + if (ResourceType->getAs<HLSLAttributedResourceType>()) { + TypeOperand = ResourceType; + } + } + } + Result = CGM.getTypes().ConvertType(TypeOperand); + break; + } + default: + llvm_unreachable("HLSLInlineSpirvType had invalid operand!"); + break; + } + + assert(Result); + Operands.push_back(Result); + } + + return llvm::TargetExtType::get(Ctx, "spirv.Type", Operands, + {SpirvType->getOpcode(), SpirvType->getSize(), + SpirvType->getAlignment()}); +} + llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType( CodeGenModule &CGM, const Type *Ty, const SmallVector<int32_t> *Packoffsets) const { + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + + if (auto *SpirvType = dyn_cast<HLSLInlineSpirvType>(Ty)) + return getInlineSpirvType(CGM, SpirvType); + auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty); if (!ResType) return nullptr; - llvm::LLVMContext &Ctx = CGM.getLLVMContext(); const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs(); switch (ResAttrs.ResourceClass) { case llvm::dxil::ResourceClass::UAV: |