[clang] [HLSL] Apply resource attributes to the resource type rather than the handle member (PR #107160)
Damyan Pepper via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 3 17:13:32 PDT 2024
================
@@ -556,46 +562,120 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) {
D->addAttr(NewAttr);
}
-void SemaHLSL::handleResourceClassAttr(Decl *D, const ParsedAttr &AL) {
- if (!AL.isArgIdent(0)) {
- Diag(AL.getLoc(), diag::err_attribute_argument_type)
- << AL << AANT_ArgumentIdentifier;
- return;
- }
+bool SemaHLSL::CreateHLSLAttributedResourceType(
+ Sema &S, QualType Wrapped, llvm::SmallVector<const Attr *> &AttrList,
+ QualType &ResType) {
+ assert(AttrList.size() && "expected list of resource attributes");
- IdentifierLoc *Loc = AL.getArgAsIdent(0);
- StringRef Identifier = Loc->Ident->getName();
- SourceLocation ArgLoc = Loc->Loc;
+ QualType Contained = QualType();
+ HLSLAttributedResourceType::Attributes ResAttrs = {};
- // Validate.
- llvm::dxil::ResourceClass RC;
- if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
- Diag(ArgLoc, diag::warn_attribute_type_not_supported)
- << "ResourceClass" << Identifier;
- return;
+ bool hasResourceClass = false;
+ for (auto *Attr : AttrList) {
+ if (!Attr)
+ continue;
+ switch (Attr->getKind()) {
+ case attr::HLSLResourceClass: {
+ llvm::dxil::ResourceClass RC =
+ dyn_cast<HLSLResourceClassAttr>(Attr)->getResourceClass();
+ if (!hasResourceClass) {
+ ResAttrs.ResourceClass = RC;
+ hasResourceClass = true;
+ } else if (RC != ResAttrs.ResourceClass) {
+ S.Diag(Attr->getLocation(), diag::warn_duplicate_attribute) << Attr;
+ return false;
+ }
+ break;
+ }
+ case attr::HLSLROV:
+ ResAttrs.IsROV = true;
+ break;
+ default:
+ llvm_unreachable("unhandled resource attribute type");
+ }
}
- D->addAttr(HLSLResourceClassAttr::Create(getASTContext(), RC, ArgLoc));
+ if (!hasResourceClass) {
+ S.Diag(AttrList.back()->getRange().getEnd(),
+ diag::err_missing_resource_class);
+ return false;
+ }
+
+ ResType = S.getASTContext().getHLSLAttributedResourceType(Wrapped, Contained,
+ ResAttrs);
+ return true;
}
-// 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.
+// Validates and creates an HLSL attribute that is applied as type attribute on
+// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at
+// the end of the declaration they are applied to the declaration type by
+// wrapping it in HLSLAttributedResourceType.
bool SemaHLSL::handleResourceTypeAttr(const ParsedAttr &AL) {
- // FIXME: placeholder - not yet implemented
+ Attr *A = nullptr;
+
+ // validate number of arguments
+ if (!AL.checkExactlyNumArgs(SemaRef, AL.getMinArgs()))
+ return false;
+
+ switch (AL.getKind()) {
+ case ParsedAttr::AT_HLSLResourceClass: {
+ if (!AL.isArgIdent(0)) {
+ Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIdentifier;
+ return false;
+ }
+
+ IdentifierLoc *Loc = AL.getArgAsIdent(0);
+ StringRef Identifier = Loc->Ident->getName();
+ SourceLocation ArgLoc = Loc->Loc;
+
+ // Validate resource class value
+ llvm::dxil::ResourceClass RC;
+ if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
+ Diag(ArgLoc, diag::warn_attribute_type_not_supported)
+ << "ResourceClass" << Identifier;
+ return false;
+ }
+ A = HLSLResourceClassAttr::Create(getASTContext(), RC, AL.getLoc());
+ break;
+ }
+ case ParsedAttr::AT_HLSLROV:
+ A = HLSLROVAttr::Create(getASTContext(), AL.getLoc());
+ break;
+ default:
+ llvm_unreachable("unhandled HLSL attribute");
+ }
+
+ HLSLResourcesTypeAttrs.emplace_back(A);
return true;
}
-// Combines all resource type attributes and create HLSLAttributedResourceType.
+// Combines all resource type attributes and creates HLSLAttributedResourceType.
QualType SemaHLSL::ProcessResourceTypeAttributes(QualType CurrentType) {
- // FIXME: placeholder - not yet implemented
- return CurrentType;
+ if (!HLSLResourcesTypeAttrs.size())
+ return CurrentType;
+
+ QualType QT = CurrentType;
+ if (CreateHLSLAttributedResourceType(SemaRef, CurrentType,
+ HLSLResourcesTypeAttrs, QT)) {
+ const HLSLAttributedResourceType *RT =
+ dyn_cast<HLSLAttributedResourceType>(QT.getTypePtr());
+ SourceLocation Loc = HLSLResourcesTypeAttrs[0]->getLoc();
+ LocsForHLSLAttributedResources.insert(std::pair(RT, Loc));
+ }
+ HLSLResourcesTypeAttrs.clear();
+ return QT;
}
// Returns source location for the HLSLAttributedResourceType
SourceLocation
SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {
- // FIXME: placeholder - not yet implemented
+ auto I = LocsForHLSLAttributedResources.find(RT);
+ if (I != LocsForHLSLAttributedResources.end()) {
+ SourceLocation Loc = I->second;
+ LocsForHLSLAttributedResources.erase(RT);
----------------
damyanp wrote:
```suggestion
LocsForHLSLAttributedResources.erase(I);
```
Doing this should mean we can avoid looking up RT in the map a second time since we already know where it is with `I`.
https://github.com/llvm/llvm-project/pull/107160
More information about the cfe-commits
mailing list