aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorCassandra Beckley <beckl.ds@gmail.com>2025-05-27 08:40:54 -0700
committerGitHub <noreply@github.com>2025-05-27 11:40:54 -0400
commit5a4571133af78e365e6e7b271688b9ceaa653e67 (patch)
tree5018fb04b5ca4301262735fb16d7d27a20414799 /clang/lib/CodeGen
parent58f80536d3ee1a9ca3e8aa62da92d33d4bc9cc8c (diff)
downloadllvm-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.cpp8
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.h1
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp5
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp2
-rw-r--r--clang/lib/CodeGen/Targets/SPIR.cpp87
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: