[clang] [HLSL] Add HLSLAttributedResourceType (PR #106181)

Helena Kotas via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 26 22:11:49 PDT 2024


https://github.com/hekota created https://github.com/llvm/llvm-project/pull/106181

Introducing `HLSLAttributedResourceType` - a new type that is similar to `AttributedType` but with additional data specific to HLSL resources. `AttributeType` currently only stores an attribute kind and no additional data from the type attributes parameters. This does not work for the HLSL resource type since its type attributes contain non-boolean values that need to be retained as well.

For example:

```
template <typename T> class RWBuffer {
  __hlsl_resource_t  [[hlsl::resource_class(uav)]] [[hlsl::is_rov]] handle;
};
```

The data `HLSLAttributedResourceType` needs to potentially store are:
- resource class (SRV, UAV, CBuffer, Sampler)
- texture dimension(1-3)
- flags is_rov, is_array, is_feedback and is_multisample
- contained type

All of these values except contained type will be stored in `HLSLAttributedResourceType::Attributes` struct and accessed individually via the fields. There is also `Data` alias that covers all of these values as a `unsigned` which is used for the AST type serialization.

During type attribute processing all HLSL type attributes will be validated and collected by SemaHLSL (by `SemaHLSL::handleResourceTypeAttr`) and in the end combined into a single `HLSLAttributedResourceType` instance (in  `SemaHLSL::ProcessResourceTypeAttributes`). `SemaHLSL` will also need to short-term store the `TypeLoc` information for the new type that will be grabbed by `TypeSpecLocFiller` soon after the type is created.

Part 1/2 of #104861

>From 11a6b3aac44889d39911a6704a9a963f29e92388 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 26 Aug 2024 12:13:09 -0700
Subject: [PATCH 1/2] Add HLSLAttributedResourceType - WIP

---
 clang/include/clang-c/Index.h                 |  5 +-
 clang/include/clang/AST/ASTContext.h          |  5 ++
 clang/include/clang/AST/ASTNodeTraverser.h    |  5 ++
 clang/include/clang/AST/RecursiveASTVisitor.h |  6 ++
 clang/include/clang/AST/Type.h                | 57 +++++++++++++++++++
 clang/include/clang/AST/TypeLoc.h             | 23 ++++++++
 clang/include/clang/AST/TypeProperties.td     | 15 +++++
 clang/include/clang/Basic/TypeNodes.td        |  1 +
 .../clang/Serialization/TypeBitCodes.def      |  1 +
 clang/lib/AST/ASTContext.cpp                  | 27 +++++++++
 clang/lib/AST/ASTImporter.cpp                 | 16 ++++++
 clang/lib/AST/ASTStructuralEquivalence.cpp    |  7 +++
 clang/lib/AST/ItaniumMangle.cpp               |  1 +
 clang/lib/AST/TypeLoc.cpp                     |  5 ++
 clang/lib/AST/TypePrinter.cpp                 | 24 ++++++++
 clang/lib/CodeGen/CGDebugInfo.cpp             |  1 +
 clang/lib/CodeGen/CodeGenFunction.cpp         |  1 +
 clang/lib/Sema/SemaExpr.cpp                   |  1 +
 clang/lib/Sema/SemaType.cpp                   | 22 +++++++
 clang/lib/Sema/TreeTransform.h                |  7 +++
 clang/lib/Serialization/ASTReader.cpp         |  5 ++
 clang/lib/Serialization/ASTWriter.cpp         |  6 ++
 clang/tools/libclang/CIndex.cpp               |  5 ++
 clang/tools/libclang/CXType.cpp               |  1 +
 24 files changed, 245 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index f78f4f1b2e6c9f..4f99bf4ebe309b 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2980,8 +2980,9 @@ enum CXTypeKind {
   CXType_Atomic = 177,
   CXType_BTFTagAttributed = 178,
 
-  // HLSL Intangible Types
-  CXType_HLSLResource = 179
+  // HLSL Types
+  CXType_HLSLResource = 179,
+  CXType_HLSLAttributedResource = 180
 };
 
 /**
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 58a820508da42b..4026eca1938144 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -254,6 +254,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::ContextualFoldingSet<DependentBitIntType, ASTContext &>
       DependentBitIntTypes;
   llvm::FoldingSet<BTFTagAttributedType> BTFTagAttributedTypes;
+  llvm::FoldingSet<HLSLAttributedResourceType> HLSLAttributedResourceTypes;
 
   mutable llvm::FoldingSet<CountAttributedType> CountAttributedTypes;
 
@@ -1671,6 +1672,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
                                    QualType Wrapped);
 
+  QualType
+  getHLSLAttributedResourceType(QualType Wrapped, QualType Contained,
+                                HLSLAttributedResourceType::Attributes &Attrs);
+
   QualType
   getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
                                unsigned Index,
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 0546c19ce81195..a443a88bab1f2d 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -439,6 +439,11 @@ class ASTNodeTraverser
   void VisitBTFTagAttributedType(const BTFTagAttributedType *T) {
     Visit(T->getWrappedType());
   }
+  void VisitHLSLAttributedResourceType(const HLSLAttributedResourceType *T) {
+    QualType Contained = T->getContainedType();
+    if (!Contained.isNull())
+      Visit(Contained);
+  }
   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {}
   void
   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 2b35997bd539ac..e51b04cce39eb9 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1146,6 +1146,9 @@ DEF_TRAVERSE_TYPE(CountAttributedType, {
 DEF_TRAVERSE_TYPE(BTFTagAttributedType,
                   { TRY_TO(TraverseType(T->getWrappedType())); })
 
+DEF_TRAVERSE_TYPE(HLSLAttributedResourceType,
+                  { TRY_TO(TraverseType(T->getWrappedType())); })
+
 DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
 
 DEF_TRAVERSE_TYPE(MacroQualifiedType,
@@ -1445,6 +1448,9 @@ DEF_TRAVERSE_TYPELOC(CountAttributedType,
 DEF_TRAVERSE_TYPELOC(BTFTagAttributedType,
                      { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); })
 
+DEF_TRAVERSE_TYPELOC(HLSLAttributedResourceType,
+                     { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); })
+
 DEF_TRAVERSE_TYPELOC(ElaboratedType, {
   if (TL.getQualifierLoc()) {
     TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 27618604192c51..1afe6805bfa322 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -67,6 +67,7 @@ class ValueDecl;
 class TagDecl;
 class TemplateParameterList;
 class Type;
+class Attr;
 
 enum {
   TypeAlignmentInBits = 4,
@@ -6150,6 +6151,60 @@ class BTFTagAttributedType : public Type, public llvm::FoldingSetNode {
   }
 };
 
+class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
+public:
+  struct Attributes {
+    union {
+      struct {
+        uint8_t ResourceClass; // maps to llvm::dxil::ResourceClass
+        uint8_t IsROV : 1;
+        uint8_t Dimension : 2;
+        uint8_t IsArray : 1;
+        uint8_t IsMultisample : 1;
+        uint8_t IsFeedback : 1;
+      };
+      unsigned Data;
+    };
+    Attributes() : Data() {}
+  };
+  static_assert(sizeof(Attributes) == sizeof(Attributes::Data));
+
+private:
+  friend class ASTContext; // ASTContext creates these
+
+  QualType WrappedType;
+  QualType ContainedType;
+  const Attributes Attrs;
+
+  HLSLAttributedResourceType(QualType Canon, QualType Wrapped,
+                             QualType Contained, const Attributes &Attrs)
+      : Type(HLSLAttributedResource, Canon, Wrapped->getDependence()),
+        WrappedType(Wrapped), ContainedType(Contained), Attrs(Attrs) {}
+
+public:
+  QualType getWrappedType() const { return WrappedType; }
+  QualType getContainedType() const { return ContainedType; }
+  const Attributes &getAttrs() const { return Attrs; }
+
+  bool isSugared() const { return true; }
+  QualType desugar() const { return getWrappedType(); }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, WrappedType, ContainedType, Attrs);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped,
+                      QualType Contained, const Attributes &Attrs) {
+    ID.AddPointer(Wrapped.getAsOpaquePtr());
+    ID.AddPointer(Contained.getAsOpaquePtr());
+    ID.AddInteger(Attrs.Data);
+  }
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == HLSLAttributedResource;
+  }
+};
+
 class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
   friend class ASTContext; // ASTContext creates these
 
@@ -8573,6 +8628,8 @@ template <typename T> const T *Type::getAsAdjusted() const {
       Ty = A->getModifiedType().getTypePtr();
     else if (const auto *A = dyn_cast<BTFTagAttributedType>(Ty))
       Ty = A->getWrappedType().getTypePtr();
+    else if (const auto *A = dyn_cast<HLSLAttributedResourceType>(Ty))
+      Ty = A->getWrappedType().getTypePtr();
     else if (const auto *E = dyn_cast<ElaboratedType>(Ty))
       Ty = E->desugar().getTypePtr();
     else if (const auto *P = dyn_cast<ParenType>(Ty))
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 9f2dff7a782cb3..88809eb73adb06 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -940,6 +940,27 @@ class BTFTagAttributedTypeLoc
   QualType getInnerType() const { return getTypePtr()->getWrappedType(); }
 };
 
+struct HLSLAttributedResourceLocInfo {
+  SourceRange Range;
+};
+
+/// Type source information for an btf_tag attributed type.
+class HLSLAttributedResourceTypeLoc
+    : public ConcreteTypeLoc<UnqualTypeLoc, HLSLAttributedResourceTypeLoc,
+                             HLSLAttributedResourceType,
+                             HLSLAttributedResourceLocInfo> {
+public:
+  TypeLoc getWrappedLoc() const { return getInnerTypeLoc(); }
+
+  void setSourceRange(const SourceRange &R) { getLocalData()->Range = R; }
+
+  SourceRange getLocalSourceRange() const { return getLocalData()->Range; }
+
+  void initializeLocal(ASTContext &Context, SourceLocation loc) { setSourceRange(SourceRange()); }
+
+  QualType getInnerType() const { return getTypePtr()->getWrappedType(); }
+};
+
 struct ObjCObjectTypeLocInfo {
   SourceLocation TypeArgsLAngleLoc;
   SourceLocation TypeArgsRAngleLoc;
@@ -2690,6 +2711,8 @@ inline T TypeLoc::getAsAdjusted() const {
       Cur = ATL.getModifiedLoc();
     else if (auto ATL = Cur.getAs<BTFTagAttributedTypeLoc>())
       Cur = ATL.getWrappedLoc();
+    else if (auto ATL = Cur.getAs<HLSLAttributedResourceTypeLoc>())
+      Cur = ATL.getWrappedLoc();
     else if (auto ETL = Cur.getAs<ElaboratedTypeLoc>())
       Cur = ETL.getNamedTypeLoc();
     else if (auto ATL = Cur.getAs<AdjustedTypeLoc>())
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 33398ecf5b849b..20aeee3ab688cc 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -687,6 +687,21 @@ let Class = BTFTagAttributedType in {
   }]>;
 }
 
+let Class = HLSLAttributedResourceType in {
+  // def : Property<"attrs", SmallVector<Attr*, 4>> {
+  //   let Read = [{ node->getAttr() }];
+  // }
+  def : Property<"wrappedType", QualType> {
+    let Read = [{ node->getWrappedType() }];
+  }
+
+  def : Creator<[{
+    llvm_unreachable("FIXME");
+    (void)ctx;
+    //return ctx.getHLSLAttributedResourceType(attrs, wrappedType);
+  }]>;
+}
+
 let Class = DependentAddressSpaceType in {
   def : Property<"pointeeType", QualType> {
     let Read = [{ node->getPointeeType() }];
diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
index fee49cf4326dfc..8cca392cddc174 100644
--- a/clang/include/clang/Basic/TypeNodes.td
+++ b/clang/include/clang/Basic/TypeNodes.td
@@ -93,6 +93,7 @@ def EnumType : TypeNode<TagType>, LeafType;
 def ElaboratedType : TypeNode<Type>, NeverCanonical;
 def AttributedType : TypeNode<Type>, NeverCanonical;
 def BTFTagAttributedType : TypeNode<Type>, NeverCanonical;
+def HLSLAttributedResourceType : TypeNode<Type>, NeverCanonical;
 def TemplateTypeParmType : TypeNode<Type>, AlwaysDependent, LeafType;
 def SubstTemplateTypeParmType : TypeNode<Type>, NeverCanonical;
 def SubstTemplateTypeParmPackType : TypeNode<Type>, AlwaysDependent;
diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def
index 82b053d4caca63..3c78b878050101 100644
--- a/clang/include/clang/Serialization/TypeBitCodes.def
+++ b/clang/include/clang/Serialization/TypeBitCodes.def
@@ -67,5 +67,6 @@ TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55)
 TYPE_BIT_CODE(PackIndexing, PACK_INDEXING, 56)
 TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57)
 TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58)
+TYPE_BIT_CODE(HLSLAttributedResource, HLSLRESOURCE_ATTRIBUTED, 59)
 
 #undef TYPE_BIT_CODE
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b201d201e1ea6a..f77aaef059db78 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2406,6 +2406,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
     return getTypeInfo(
         cast<BTFTagAttributedType>(T)->getWrappedType().getTypePtr());
 
+  case Type::HLSLAttributedResource:
+    return getTypeInfo(
+        cast<HLSLAttributedResourceType>(T)->getWrappedType().getTypePtr());
+
   case Type::Atomic: {
     // Start with the base type information.
     TypeInfo Info = getTypeInfo(cast<AtomicType>(T)->getValueType());
@@ -5219,6 +5223,28 @@ QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
   return QualType(Ty, 0);
 }
 
+QualType ASTContext::getHLSLAttributedResourceType(
+    QualType Wrapped, QualType Contained,
+    HLSLAttributedResourceType::Attributes &Attrs) {
+
+  llvm::FoldingSetNodeID ID;
+  HLSLAttributedResourceType::Profile(ID, Wrapped, Contained, Attrs);
+
+  void *InsertPos = nullptr;
+  HLSLAttributedResourceType *Ty =
+      HLSLAttributedResourceTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (Ty)
+    return QualType(Ty, 0);
+
+  QualType Canon = getCanonicalType(Wrapped);
+  Ty = new (*this, alignof(HLSLAttributedResourceType))
+      HLSLAttributedResourceType(Canon, Wrapped, Contained, Attrs);
+
+  Types.push_back(Ty);
+  HLSLAttributedResourceTypes.InsertNode(Ty, InsertPos);
+
+  return QualType(Ty, 0);
+}
 /// Retrieve a substitution-result type.
 QualType ASTContext::getSubstTemplateTypeParmType(
     QualType Replacement, Decl *AssociatedDecl, unsigned Index,
@@ -13584,6 +13610,7 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
     CANONICAL_TYPE(FunctionNoProto)
     CANONICAL_TYPE(FunctionProto)
     CANONICAL_TYPE(IncompleteArray)
+    CANONICAL_TYPE(HLSLAttributedResource)
     CANONICAL_TYPE(LValueReference)
     CANONICAL_TYPE(MemberPointer)
     CANONICAL_TYPE(ObjCInterface)
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3bc0a647ebf94f..07162b43b125a0 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1832,6 +1832,22 @@ ExpectedType clang::ASTNodeImporter::VisitBTFTagAttributedType(
                                                          ToWrappedType);
 }
 
+ExpectedType clang::ASTNodeImporter::VisitHLSLAttributedResourceType(
+    const clang::HLSLAttributedResourceType *T) {
+  // FIXME:
+  llvm_unreachable(
+      "ASTNodeImporter::VisitHLSLAttributedResourceType not yet implemented");
+
+  // Error Err = Error::success();
+  // const SmallVector<Attr*,4> *ToAttrs = importChecked(Err, T->getAttrs());
+  // QualType ToWrappedType = importChecked(Err, T->getWrappedType());
+  // if (Err)
+  //   return std::move(Err);
+
+  // return Importer.getToContext().getHLSLAttributedResourceType(ToAttrs,
+  //                                                        ToWrappedType);
+}
+
 ExpectedType clang::ASTNodeImporter::VisitConstantMatrixType(
     const clang::ConstantMatrixType *T) {
   ExpectedType ToElementTypeOrErr = import(T->getElementType());
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 37555c324282fe..b49c95494bc1be 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1093,6 +1093,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
       return false;
     break;
 
+  case Type::HLSLAttributedResource:
+    if (!IsStructurallyEquivalent(
+            Context, cast<HLSLAttributedResourceType>(T1)->getWrappedType(),
+            cast<HLSLAttributedResourceType>(T2)->getWrappedType()))
+      return false;
+    break;
+
   case Type::Paren:
     if (!IsStructurallyEquivalent(Context, cast<ParenType>(T1)->getInnerType(),
                                   cast<ParenType>(T2)->getInnerType()))
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 976670d1efa561..1ca449427f60df 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2419,6 +2419,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
   case Type::Paren:
   case Type::Attributed:
   case Type::BTFTagAttributed:
+  case Type::HLSLAttributedResource:
   case Type::Auto:
   case Type::DeducedTemplateSpecialization:
   case Type::PackExpansion:
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 0d653d6faaa829..8aada7e603407e 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -726,6 +726,11 @@ namespace {
       return Visit(T.getWrappedLoc());
     }
 
+    TypeLoc
+    VisitHLSLAttributedResourceTypeLoc(HLSLAttributedResourceTypeLoc T) {
+      return Visit(T.getWrappedLoc());
+    }
+
     TypeLoc VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc T) {
       return Visit(T.getInnerLoc());
     }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index f9bf63aa86e731..056d226b8bb819 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -12,6 +12,7 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/Attrs.inc"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
@@ -39,6 +40,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/raw_ostream.h"
@@ -247,6 +249,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
     case Type::BitInt:
     case Type::DependentBitInt:
     case Type::BTFTagAttributed:
+    case Type::HLSLAttributedResource:
       CanPrefixQualifiers = true;
       break;
 
@@ -1927,6 +1930,10 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
   case attr::BTFTypeTag:
     llvm_unreachable("BTFTypeTag attribute handled separately");
 
+  case attr::HLSLResourceClass:
+  case attr::HLSLROV:
+    llvm_unreachable("HLSL resource attributes handled separately");
+
   case attr::OpenCLPrivateAddressSpace:
   case attr::OpenCLGlobalAddressSpace:
   case attr::OpenCLGlobalDeviceAddressSpace:
@@ -2048,6 +2055,23 @@ void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
   printAfter(T->getWrappedType(), OS);
 }
 
+void TypePrinter::printHLSLAttributedResourceBefore(
+    const HLSLAttributedResourceType *T, raw_ostream &OS) {
+  printBefore(T->getWrappedType(), OS);
+  const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();
+  OS << " [[hlsl::resource_class("
+     << HLSLResourceClassAttr::ConvertResourceClassToStr(
+            static_cast<llvm::dxil::ResourceClass>(Attrs.ResourceClass))
+     << "]]";
+  if (Attrs.IsROV)
+    OS << " [[hlsl::is_rov()]]";
+}
+
+void TypePrinter::printHLSLAttributedResourceAfter(
+    const HLSLAttributedResourceType *T, raw_ostream &OS) {
+  printAfter(T->getWrappedType(), OS);
+}
+
 void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
                                            raw_ostream &OS) {
   OS << T->getDecl()->getName();
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 7ad3088f0ab756..ebd4015a7e8afa 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3850,6 +3850,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
   case Type::Auto:
   case Type::Attributed:
   case Type::BTFTagAttributed:
+  case Type::HLSLAttributedResource:
   case Type::Adjusted:
   case Type::Decayed:
   case Type::DeducedTemplateSpecialization:
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index eff8c9f5694084..4c1c2e38ea474f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2482,6 +2482,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
     case Type::UnaryTransform:
     case Type::Attributed:
     case Type::BTFTagAttributed:
+    case Type::HLSLAttributedResource:
     case Type::SubstTemplateTypeParm:
     case Type::MacroQualified:
     case Type::CountAttributed:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c67183df335dd5..75d99a724e07c5 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4467,6 +4467,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
     case Type::UnaryTransform:
     case Type::Attributed:
     case Type::BTFTagAttributed:
+    case Type::HLSLAttributedResource:
     case Type::SubstTemplateTypeParm:
     case Type::MacroQualified:
     case Type::CountAttributed:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 4b1bb05464f7dc..387389c23e95e5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/Specifiers.h"
@@ -37,6 +38,7 @@
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaCUDA.h"
+#include "clang/Sema/SemaHLSL.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/SemaObjC.h"
 #include "clang/Sema/SemaOpenMP.h"
@@ -1546,6 +1548,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
       Result = Qualified;
   }
 
+  if (S.getLangOpts().HLSL)
+    Result = S.HLSL().ProcessResourceTypeAttributes(Result);
+
   assert(!Result.isNull() && "This function should not return a null type");
   return Result;
 }
@@ -5783,6 +5788,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
   TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
 }
 
+static void fillHLSLAttributedResourceTypeLoc(HLSLAttributedResourceTypeLoc TL, TypeProcessingState &State) { 
+  TL.setSourceRange(State.getSema().HLSL().TakeLocForHLSLAttribute(TL.getTypePtr()));
+}
+
 static void fillMatrixTypeLoc(MatrixTypeLoc MTL,
                               const ParsedAttributesView &Attrs) {
   for (const ParsedAttr &AL : Attrs) {
@@ -5817,6 +5826,10 @@ namespace {
     void VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
       Visit(TL.getWrappedLoc());
     }
+    void VisitHLSLAttributedResourceTypeLoc(HLSLAttributedResourceTypeLoc TL) {
+      Visit(TL.getWrappedLoc());
+      fillHLSLAttributedResourceTypeLoc(TL, State);
+    }
     void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
       Visit(TL.getInnerLoc());
       TL.setExpansionLoc(
@@ -6067,6 +6080,9 @@ namespace {
     void VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
       // nothing
     }
+    void VisitHLSLResourcedAttributedTypeLoc(HLSLAttributedResourceTypeLoc TL) {
+      // nothing
+    }
     void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
       // nothing
     }
@@ -8803,6 +8819,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
       attr.setUsedAsTypeAttr();
       break;
     }
+    case ParsedAttr::AT_HLSLResourceClass:
+    case ParsedAttr::AT_HLSLROV: {
+      if (state.getSema().HLSL().handleResourceTypeAttr(attr))
+        attr.setUsedAsTypeAttr();
+      break;
+    }
     }
 
     // Handle attributes that are defined in a macro. We do not want this to be
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 62287c2d26375c..5a54b0aa53c6df 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -7453,6 +7453,13 @@ QualType TreeTransform<Derived>::TransformBTFTagAttributedType(
   llvm_unreachable("Unexpected TreeTransform for BTFTagAttributedType");
 }
 
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformHLSLAttributedResourceType(
+    TypeLocBuilder &TLB, HLSLAttributedResourceTypeLoc TL) {
+  llvm_unreachable(
+      "Unexpected TreeTransform for HLSLAttributedResourceTypeLoc");
+}
+
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB,
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index fa9b815239dbb6..daf8d7343ea237 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7049,6 +7049,11 @@ void TypeLocReader::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
   // Nothing to do.
 }
 
+void TypeLocReader::VisitHLSLAttributedResourceTypeLoc(
+    HLSLAttributedResourceTypeLoc TL) {
+  // Nothing to do.
+}
+
 void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
   TL.setNameLoc(readSourceLocation());
 }
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 5cfb98c2a1060a..62f41d7ea0e096 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -34,6 +34,7 @@
 #include "clang/AST/RawCommentList.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeLocVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
@@ -559,6 +560,11 @@ void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
   // Nothing to do.
 }
 
+void TypeLocWriter::VisitHLSLAttributedResourceTypeLoc(
+    HLSLAttributedResourceTypeLoc TL) {
+  // Nothing to do.
+}
+
 void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
   addSourceLocation(TL.getNameLoc());
 }
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 66636f2c665feb..08562e05ab658d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1787,6 +1787,11 @@ bool CursorVisitor::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
   return Visit(TL.getWrappedLoc());
 }
 
+bool CursorVisitor::VisitHLSLAttributedResourceTypeLoc(
+    HLSLAttributedResourceTypeLoc TL) {
+  return Visit(TL.getWrappedLoc());
+}
+
 bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
                                          bool SkipResultType) {
   if (!SkipResultType && Visit(TL.getReturnLoc()))
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index f5d1fbf30c7dc4..b4df12405cf356 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -620,6 +620,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
     TKIND(Pipe);
     TKIND(Attributed);
     TKIND(BTFTagAttributed);
+    TKIND(HLSLAttributedResource);
     TKIND(BFloat16);
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id);
 #include "clang/Basic/OpenCLImageTypes.def"

>From 35442efb6c4268f708cd9206bc9585b3a1a012f7 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Mon, 26 Aug 2024 21:36:01 -0700
Subject: [PATCH 2/2] Add placeholders in SemaHLSL, implement serialization and
 add comments.

---
 clang/include/clang/AST/ASTContext.h      |  6 +++---
 clang/include/clang/AST/Type.h            | 11 +++++++----
 clang/include/clang/AST/TypeProperties.td | 17 +++++++++--------
 clang/include/clang/Sema/SemaHLSL.h       |  4 ++++
 clang/lib/AST/ASTContext.cpp              |  2 +-
 clang/lib/AST/ASTImporter.cpp             | 21 +++++++++------------
 clang/lib/AST/TypePrinter.cpp             | 12 +-----------
 clang/lib/Sema/SemaHLSL.cpp               | 22 ++++++++++++++++++++++
 8 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 4026eca1938144..8156d283f8fe21 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1672,9 +1672,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
                                    QualType Wrapped);
 
-  QualType
-  getHLSLAttributedResourceType(QualType Wrapped, QualType Contained,
-                                HLSLAttributedResourceType::Attributes &Attrs);
+  QualType getHLSLAttributedResourceType(
+      QualType Wrapped, QualType Contained,
+      const HLSLAttributedResourceType::Attributes &Attrs);
 
   QualType
   getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 1afe6805bfa322..dde3e2347bd5eb 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -6154,18 +6154,21 @@ class BTFTagAttributedType : public Type, public llvm::FoldingSetNode {
 class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
 public:
   struct Attributes {
+    // This is where data gathered from HLSL resource attributes are stored,
+    // such as resource class, is_rov, dimension, is_array, is_feedback 
+    // or is_multisample. The values will be accessed individually via fields
+    // on the embedded struct. The Data alias is used for the AST type
+    //  serialization.
     union {
       struct {
         uint8_t ResourceClass; // maps to llvm::dxil::ResourceClass
         uint8_t IsROV : 1;
-        uint8_t Dimension : 2;
-        uint8_t IsArray : 1;
-        uint8_t IsMultisample : 1;
-        uint8_t IsFeedback : 1;
+        // FIXME: add additional resource properties here
       };
       unsigned Data;
     };
     Attributes() : Data() {}
+    Attributes(unsigned Data) : Data(Data) {}
   };
   static_assert(sizeof(Attributes) == sizeof(Attributes::Data));
 
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 20aeee3ab688cc..bb4961d83df239 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -688,17 +688,18 @@ let Class = BTFTagAttributedType in {
 }
 
 let Class = HLSLAttributedResourceType in {
-  // def : Property<"attrs", SmallVector<Attr*, 4>> {
-  //   let Read = [{ node->getAttr() }];
-  // }
-  def : Property<"wrappedType", QualType> {
+  def : Property<"attrsData", UInt32> {
+    let Read = [{ node->getAttrs().Data }];
+  }
+  def : Property<"wrappedTy", QualType> {
     let Read = [{ node->getWrappedType() }];
   }
-
+  def : Property<"containedTy", QualType> {
+    let Read = [{ node->getContainedType() }];
+  }
   def : Creator<[{
-    llvm_unreachable("FIXME");
-    (void)ctx;
-    //return ctx.getHLSLAttributedResourceType(attrs, wrappedType);
+    return ctx.getHLSLAttributedResourceType(wrappedTy, containedTy,
+                            HLSLAttributedResourceType::Attributes(attrsData));
   }]>;
 }
 
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 3aae3383c215b5..d1b98d40f0420f 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -59,8 +59,12 @@ class SemaHLSL : public SemaBase {
   void handleResourceClassAttr(Decl *D, const ParsedAttr &AL);
   void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
   void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
+  bool handleResourceTypeAttr(const ParsedAttr &AL);
 
   bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  QualType ProcessResourceTypeAttributes(QualType Wrapped);
+  SourceLocation TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT);
 };
 
 } // namespace clang
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f77aaef059db78..f108952d7bbf73 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5225,7 +5225,7 @@ QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
 
 QualType ASTContext::getHLSLAttributedResourceType(
     QualType Wrapped, QualType Contained,
-    HLSLAttributedResourceType::Attributes &Attrs) {
+    const HLSLAttributedResourceType::Attributes &Attrs) {
 
   llvm::FoldingSetNodeID ID;
   HLSLAttributedResourceType::Profile(ID, Wrapped, Contained, Attrs);
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 07162b43b125a0..fa850409ba1210 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1834,18 +1834,15 @@ ExpectedType clang::ASTNodeImporter::VisitBTFTagAttributedType(
 
 ExpectedType clang::ASTNodeImporter::VisitHLSLAttributedResourceType(
     const clang::HLSLAttributedResourceType *T) {
-  // FIXME:
-  llvm_unreachable(
-      "ASTNodeImporter::VisitHLSLAttributedResourceType not yet implemented");
-
-  // Error Err = Error::success();
-  // const SmallVector<Attr*,4> *ToAttrs = importChecked(Err, T->getAttrs());
-  // QualType ToWrappedType = importChecked(Err, T->getWrappedType());
-  // if (Err)
-  //   return std::move(Err);
-
-  // return Importer.getToContext().getHLSLAttributedResourceType(ToAttrs,
-  //                                                        ToWrappedType);
+  Error Err = Error::success();
+  const HLSLAttributedResourceType::Attributes &ToAttrs = T->getAttrs();
+  QualType ToWrappedType = importChecked(Err, T->getWrappedType());
+  QualType ToContainedType = importChecked(Err, T->getContainedType());
+  if (Err)
+    return std::move(Err);
+
+  return Importer.getToContext().getHLSLAttributedResourceType(
+      ToWrappedType, ToContainedType, ToAttrs);
 }
 
 ExpectedType clang::ASTNodeImporter::VisitConstantMatrixType(
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 056d226b8bb819..3d720739f5c115 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1930,10 +1930,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
   case attr::BTFTypeTag:
     llvm_unreachable("BTFTypeTag attribute handled separately");
 
-  case attr::HLSLResourceClass:
-  case attr::HLSLROV:
-    llvm_unreachable("HLSL resource attributes handled separately");
-
   case attr::OpenCLPrivateAddressSpace:
   case attr::OpenCLGlobalAddressSpace:
   case attr::OpenCLGlobalDeviceAddressSpace:
@@ -2058,13 +2054,7 @@ void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,
 void TypePrinter::printHLSLAttributedResourceBefore(
     const HLSLAttributedResourceType *T, raw_ostream &OS) {
   printBefore(T->getWrappedType(), OS);
-  const HLSLAttributedResourceType::Attributes &Attrs = T->getAttrs();
-  OS << " [[hlsl::resource_class("
-     << HLSLResourceClassAttr::ConvertResourceClassToStr(
-            static_cast<llvm::dxil::ResourceClass>(Attrs.ResourceClass))
-     << "]]";
-  if (Attrs.IsROV)
-    OS << " [[hlsl::is_rov()]]";
+  // FIXME: print values of resource type attributes here
 }
 
 void TypePrinter::printHLSLAttributedResourceAfter(
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index df01549cc2eeb6..37e989a4c08122 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Sema.h"
@@ -459,6 +460,27 @@ void SemaHLSL::handleResourceClassAttr(Decl *D, const ParsedAttr &AL) {
   D->addAttr(HLSLResourceClassAttr::Create(getASTContext(), RC, ArgLoc));
 }
 
+// Validates HLSL resource type attribute and adds it to the list to be
+// processed into a single HLSLAttributedResourceType later on.
+// Returns false if the attribute is invalid.
+bool SemaHLSL::handleResourceTypeAttr(const ParsedAttr &AL) {
+  // FIXME: placeholder - not yet implemented
+  return true;
+}
+
+// Combines all resource type attributes and create HLSLAttributedResourceType.
+QualType SemaHLSL::ProcessResourceTypeAttributes(QualType CurrentType) {
+  // FIXME: placeholder - not yet implemented
+  return CurrentType;
+}
+
+// Returns source location for the HLSLAttributedResourceType
+SourceLocation
+SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {
+  // FIXME: placeholder - not yet implemented
+  return SourceLocation();
+}
+
 void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) {
   StringRef Space = "space0";
   StringRef Slot = "";



More information about the cfe-commits mailing list