Author: Xiang Li Date: 2022-10-05T09:23:35-07:00 New Revision: 15aa64301ab146dec7c6ffcd0418ed834bf099e2
URL: https://github.com/llvm/llvm-project/commit/15aa64301ab146dec7c6ffcd0418ed834bf099e2 DIFF: https://github.com/llvm/llvm-project/commit/15aa64301ab146dec7c6ffcd0418ed834bf099e2.diff LOG: [HLSL] Support register binding attribute on global variable Allow register binding attribute on variables. Report warning when register binding attribute applies to local variable or static variable. It will be ignored in this case. Type check for register binding is tracked with https://github.com/llvm/llvm-project/issues/57886. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D134617 Added: Modified: clang/include/clang/Basic/Attr.td clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseDecl.cpp clang/test/AST/HLSL/resource_binding_attr.hlsl clang/test/SemaHLSL/resource_binding_attr_error.hlsl Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1bfe4b6c48a2b..fa718b51d8134 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -133,6 +133,12 @@ def SharedVar : SubsetSubject<Var, def GlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage()}], "global variables">; +def ExternalGlobalVar : SubsetSubject<Var, + [{S->hasGlobalStorage() && + S->getStorageClass()!=StorageClass::SC_Static && + !S->isLocalExternDecl()}], + "external global variables">; + def InlineFunction : SubsetSubject<Function, [{S->isInlineSpecified()}], "inline functions">; @@ -3992,7 +3998,7 @@ def HLSLSV_GroupIndex: HLSLAnnotationAttr { def HLSLResourceBinding: InheritableAttr { let Spellings = [HLSLSemantic<"register">]; - let Subjects = SubjectList<[HLSLBufferObj, GlobalVar]>; + let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>; let LangOpts = [HLSL]; let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>]; let Documentation = [HLSLResourceBindingDocs]; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index cb396b8b54122..c518ce5487bd8 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2881,8 +2881,19 @@ class Parser : public CodeCompletionHandler { Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, const IdentifierInfo *EnclosingScope = nullptr); + void MaybeParseHLSLSemantics(Declarator &D, + SourceLocation *EndLoc = nullptr) { + assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only"); + if (Tok.is(tok::colon)) { + ParsedAttributes Attrs(AttrFactory); + ParseHLSLSemantics(Attrs, EndLoc); + D.takeAttributes(Attrs); + } + } + void MaybeParseHLSLSemantics(ParsedAttributes &Attrs, SourceLocation *EndLoc = nullptr) { + assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only"); if (getLangOpts().HLSL && Tok.is(tok::colon)) ParseHLSLSemantics(Attrs, EndLoc); } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index dfedbf5b2d779..ddb83a8c6694d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2054,6 +2054,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, return nullptr; } + if (getLangOpts().HLSL) + MaybeParseHLSLSemantics(D); + if (Tok.is(tok::kw_requires)) ParseTrailingRequiresClause(D); @@ -2223,6 +2226,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); ParseDeclarator(D); + + if (getLangOpts().HLSL) + MaybeParseHLSLSemantics(D); + if (!D.isInvalidType()) { // C++2a [dcl.decl]p1 // init-declarator: @@ -7165,7 +7172,8 @@ void Parser::ParseParameterDeclarationClause( // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); - MaybeParseHLSLSemantics(DS.getAttributes()); + if (getLangOpts().HLSL) + MaybeParseHLSLSemantics(DS.getAttributes()); if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl index ecb7e3ab98db5..6836071971111 100644 --- a/clang/test/AST/HLSL/resource_binding_attr.hlsl +++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl @@ -22,3 +22,16 @@ float foo() { // CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <col:14> 'float' lvalue Var 0x[[B]] 'b' 'float' return a + b; } + +// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV 'RWBuffer<float>':'hlsl::RWBuffer<>' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} <col:17> 'RWBuffer<float>':'hlsl::RWBuffer<>' 'void ()' +// CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} <col:23> "u3" "space0" +RWBuffer<float> UAV : register(u3); + +// CHECK: -VarDecl 0x{{[0-9a-f]+}} <{{.*}}> col:17 UAV1 'RWBuffer<float>':'hlsl::RWBuffer<>' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} <col:17> 'RWBuffer<float>':'hlsl::RWBuffer<>' 'void ()' +// CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} <col:24> "u2" "space0" +// CHECK-NEXT:-VarDecl 0x{{[0-9a-f]+}} <col:1, col:38> col:38 UAV2 'RWBuffer<float>':'hlsl::RWBuffer<>' callinit +// CHECK-NEXT:-CXXConstructExpr 0x{{[0-9a-f]+}} <col:38> 'RWBuffer<float>':'hlsl::RWBuffer<>' 'void ()' +// CHECK-NEXT:-HLSLResourceBindingAttr 0x{{[0-9a-f]+}} <col:45> "u4" "space0" +RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl index 2c3f52c0caec8..95774472aaea0 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl @@ -1,10 +1,6 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify -// expected-error@+5 {{expected ';' after top level declarator}} -// expected-error@+4 {{expected ')'}} -// expected-note@+3 {{to match this '('}} -// expected-error@+2 {{a type specifier is required for all declarations}} -// expected-error@+1 {{illegal storage class on file-scoped variable}} +// expected-error@+1 {{invalid resource class specifier 'c' used; expected 'b', 's', 't', or 'u'}} float a : register(c0, space1); // expected-error@+1 {{invalid resource class specifier 'i' used; expected 'b', 's', 't', or 'u'}} @@ -36,3 +32,29 @@ cbuffer C : register(b 2) {} // expected-error@+2 {{wrong argument format for hlsl attribute, use b2 instead}} // expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}} cbuffer D : register(b 2, space 3) {} + +// expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} +static RWBuffer<float> U : register(u5); + +void foo() { + // expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + RWBuffer<float> U : register(u3); +} +void foo2() { + // expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + extern RWBuffer<float> U2 : register(u5); +} +// FIXME: expect-error once fix https://github.com/llvm/llvm-project/issues/57886. +float b : register(u0, space1); + +// expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} +void bar(RWBuffer<float> U : register(u3)) { + +} + +struct S { + // FIXME: generate better error when support semantic on struct field. + // See https://github.com/llvm/llvm-project/issues/57889. + // expected-error@+1 {{expected expression}} + RWBuffer<float> U : register(u3); +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits