Skip to content

Commit 782ac21

Browse files
committed
[HLSL] Support cbuffer/tbuffer for hlsl.
This is first part for support cbuffer/tbuffer. The format for cbuffer/tbuffer is BufferType [Name] [: register(b#)] { VariableDeclaration [: packoffset(c#.xyzw)]; ... }; More details at https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-constants New keyword 'cbuffer' and 'tbuffer' are added. New AST node HLSLBufferDecl is added. Build AST for simple cbuffer/tbuffer without attribute support. The special thing is variables declared inside cbuffer is exposed into global scope. So isTransparentContext should return true for HLSLBuffer. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D129883
1 parent 1f4d3c6 commit 782ac21

36 files changed

+566
-14
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4671,6 +4671,51 @@ class EmptyDecl : public Decl {
46714671
static bool classofKind(Kind K) { return K == Empty; }
46724672
};
46734673

4674+
/// HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
4675+
class HLSLBufferDecl final : public NamedDecl, public DeclContext {
4676+
/// LBraceLoc - The ending location of the source range.
4677+
SourceLocation LBraceLoc;
4678+
/// RBraceLoc - The ending location of the source range.
4679+
SourceLocation RBraceLoc;
4680+
/// KwLoc - The location of the cbuffer or tbuffer keyword.
4681+
SourceLocation KwLoc;
4682+
/// IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
4683+
bool IsCBuffer;
4684+
4685+
HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc,
4686+
IdentifierInfo *ID, SourceLocation IDLoc,
4687+
SourceLocation LBrace);
4688+
4689+
public:
4690+
static HLSLBufferDecl *Create(ASTContext &C, DeclContext *LexicalParent,
4691+
bool CBuffer, SourceLocation KwLoc,
4692+
IdentifierInfo *ID, SourceLocation IDLoc,
4693+
SourceLocation LBrace);
4694+
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID);
4695+
4696+
SourceRange getSourceRange() const LLVM_READONLY {
4697+
return SourceRange(getLocStart(), RBraceLoc);
4698+
}
4699+
SourceLocation getLocStart() const LLVM_READONLY { return KwLoc; }
4700+
SourceLocation getLBraceLoc() const { return LBraceLoc; }
4701+
SourceLocation getRBraceLoc() const { return RBraceLoc; }
4702+
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
4703+
bool isCBuffer() const { return IsCBuffer; }
4704+
4705+
// Implement isa/cast/dyncast/etc.
4706+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
4707+
static bool classofKind(Kind K) { return K == HLSLBuffer; }
4708+
static DeclContext *castToDeclContext(const HLSLBufferDecl *D) {
4709+
return static_cast<DeclContext *>(const_cast<HLSLBufferDecl *>(D));
4710+
}
4711+
static HLSLBufferDecl *castFromDeclContext(const DeclContext *DC) {
4712+
return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC));
4713+
}
4714+
4715+
friend class ASTDeclReader;
4716+
friend class ASTDeclWriter;
4717+
};
4718+
46744719
/// Insertion operator for diagnostics. This allows sending NamedDecl's
46754720
/// into a diagnostic with <<.
46764721
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,

clang/include/clang/AST/JSONNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class JSONNodeDumper
246246
void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
247247
void VisitRecordDecl(const RecordDecl *RD);
248248
void VisitCXXRecordDecl(const CXXRecordDecl *RD);
249+
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
249250
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
250251
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
251252
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,8 @@ DEF_TRAVERSE_DECL(CapturedDecl, {
15381538

15391539
DEF_TRAVERSE_DECL(EmptyDecl, {})
15401540

1541+
DEF_TRAVERSE_DECL(HLSLBufferDecl, {})
1542+
15411543
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
15421544
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
15431545
})

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ class TextNodeDumper
381381
void VisitConceptDecl(const ConceptDecl *D);
382382
void
383383
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
384+
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
384385
};
385386

386387
} // namespace clang

clang/include/clang/Basic/DeclNodes.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,4 @@ def OMPRequires : DeclNode<Decl>;
108108
def Empty : DeclNode<Decl>;
109109
def RequiresExprBody : DeclNode<Decl>, DeclContext;
110110
def LifetimeExtendedTemporary : DeclNode<Decl>;
111-
111+
def HLSLBuffer : DeclNode<Named, "HLSLBuffer">, DeclContext;

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,8 @@ def note_max_tokens_total_override : Note<"total token limit set here">;
16181618

16191619
def err_expected_semantic_identifier : Error<
16201620
"expected HLSL Semantic identifier">;
1621+
def err_invalid_declaration_in_hlsl_buffer : Error<
1622+
"invalid declaration inside %select{tbuffer|cbuffer}0">;
16211623
def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">;
16221624
def ext_hlsl_access_specifiers : ExtWarn<
16231625
"access specifiers are a clang HLSL extension">,

clang/include/clang/Basic/TokenKinds.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,10 @@ KEYWORD(addrspace_cast , KEYOPENCLCXX)
604604
// CUDA/HIP function attributes
605605
KEYWORD(__noinline__ , KEYCUDA)
606606

607+
// HLSL keywords.
608+
KEYWORD(cbuffer , KEYHLSL)
609+
KEYWORD(tbuffer , KEYHLSL)
610+
607611
// OpenMP Type Traits
608612
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
609613

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,7 @@ class Parser : public CodeCompletionHandler {
28212821

28222822
void ParseHLSLSemantics(ParsedAttributes &Attrs,
28232823
SourceLocation *EndLoc = nullptr);
2824+
Decl *ParseHLSLBuffer(SourceLocation &DeclEnd);
28242825

28252826
void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
28262827
if ((getLangOpts().MicrosoftExt || getLangOpts().HLSL) &&

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5962,6 +5962,12 @@ class Sema final {
59625962
SourceLocation BuiltinLoc,
59635963
SourceLocation RParenLoc);
59645964

5965+
//===---------------------------- HLSL Features -------------------------===//
5966+
Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
5967+
SourceLocation KwLoc, IdentifierInfo *Ident,
5968+
SourceLocation IdentLoc, SourceLocation LBrace);
5969+
void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
5970+
59655971
//===---------------------------- C++ Features --------------------------===//
59665972

59675973
// Act on C++ namespaces

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,10 @@ enum DeclCode {
15111511
/// A UnnamedGlobalConstantDecl record.
15121512
DECL_UNNAMED_GLOBAL_CONSTANT,
15131513

1514-
DECL_LAST = DECL_UNNAMED_GLOBAL_CONSTANT
1514+
/// A HLSLBufferDecl record.
1515+
DECL_HLSL_BUFFER,
1516+
1517+
DECL_LAST = DECL_HLSL_BUFFER
15151518
};
15161519

15171520
/// Record codes for each kind of statement or expression.

clang/lib/AST/Decl.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5210,6 +5210,40 @@ EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
52105210
return new (C, ID) EmptyDecl(nullptr, SourceLocation());
52115211
}
52125212

5213+
HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer,
5214+
SourceLocation KwLoc, IdentifierInfo *ID,
5215+
SourceLocation IDLoc, SourceLocation LBrace)
5216+
: NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)),
5217+
DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc),
5218+
IsCBuffer(CBuffer) {}
5219+
5220+
HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
5221+
DeclContext *LexicalParent, bool CBuffer,
5222+
SourceLocation KwLoc, IdentifierInfo *ID,
5223+
SourceLocation IDLoc,
5224+
SourceLocation LBrace) {
5225+
// For hlsl like this
5226+
// cbuffer A {
5227+
// cbuffer B {
5228+
// }
5229+
// }
5230+
// compiler should treat it as
5231+
// cbuffer A {
5232+
// }
5233+
// cbuffer B {
5234+
// }
5235+
// FIXME: support nested buffers if required for back-compat.
5236+
DeclContext *DC = LexicalParent;
5237+
HLSLBufferDecl *Result =
5238+
new (C, DC) HLSLBufferDecl(DC, CBuffer, KwLoc, ID, IDLoc, LBrace);
5239+
return Result;
5240+
}
5241+
5242+
HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
5243+
return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
5244+
SourceLocation(), SourceLocation());
5245+
}
5246+
52135247
//===----------------------------------------------------------------------===//
52145248
// ImportDecl Implementation
52155249
//===----------------------------------------------------------------------===//

clang/lib/AST/DeclBase.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
750750
case ObjCMethod:
751751
case ObjCProperty:
752752
case MSProperty:
753+
case HLSLBuffer:
753754
return IDNS_Ordinary;
754755
case Label:
755756
return IDNS_Label;
@@ -1193,7 +1194,7 @@ bool DeclContext::isTransparentContext() const {
11931194
if (getDeclKind() == Decl::Enum)
11941195
return !cast<EnumDecl>(this)->isScoped();
11951196

1196-
return getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export;
1197+
return isa<LinkageSpecDecl, ExportDecl, HLSLBufferDecl>(this);
11971198
}
11981199

11991200
static bool isLinkageSpecContext(const DeclContext *DC,
@@ -1258,6 +1259,15 @@ DeclContext *DeclContext::getPrimaryContext() {
12581259
// There is only one DeclContext for these entities.
12591260
return this;
12601261

1262+
case Decl::HLSLBuffer:
1263+
// Each buffer, even with the same name, is a distinct construct.
1264+
// Multiple buffers with the same name are allowed for backward
1265+
// compatibility.
1266+
// As long as buffers have unique resource bindings the names don't matter.
1267+
// The names get exposed via the CPU-side reflection API which
1268+
// supports querying bindings, so we cannot remove them.
1269+
return this;
1270+
12611271
case Decl::TranslationUnit:
12621272
return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
12631273
case Decl::Namespace:

clang/lib/AST/DeclPrinter.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ namespace {
108108
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
109109
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
110110
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
111+
void VisitHLSLBufferDecl(HLSLBufferDecl *D);
111112

112113
void printTemplateParameters(const TemplateParameterList *Params,
113114
bool OmitTemplateKW = false);
@@ -462,12 +463,9 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
462463
Terminator = nullptr;
463464
else
464465
Terminator = ";";
465-
} else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
466-
isa<ObjCImplementationDecl>(*D) ||
467-
isa<ObjCInterfaceDecl>(*D) ||
468-
isa<ObjCProtocolDecl>(*D) ||
469-
isa<ObjCCategoryImplDecl>(*D) ||
470-
isa<ObjCCategoryDecl>(*D))
466+
} else if (isa<NamespaceDecl, LinkageSpecDecl, ObjCImplementationDecl,
467+
ObjCInterfaceDecl, ObjCProtocolDecl, ObjCCategoryImplDecl,
468+
ObjCCategoryDecl, HLSLBufferDecl>(*D))
471469
Terminator = nullptr;
472470
else if (isa<EnumConstantDecl>(*D)) {
473471
DeclContext::decl_iterator Next = D;
@@ -1658,6 +1656,21 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
16581656
}
16591657
}
16601658

1659+
void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
1660+
if (D->isCBuffer())
1661+
Out << "cbuffer ";
1662+
else
1663+
Out << "tbuffer ";
1664+
1665+
Out << *D;
1666+
1667+
prettyPrintAttributes(D);
1668+
1669+
Out << " {\n";
1670+
VisitDeclContext(D);
1671+
Indent() << "}";
1672+
}
1673+
16611674
void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
16621675
Out << "#pragma omp allocate";
16631676
if (!D->varlist_empty()) {

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,11 @@ void JSONNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *RD) {
901901
}
902902
}
903903

904+
void JSONNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
905+
VisitNamedDecl(D);
906+
JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer");
907+
}
908+
904909
void JSONNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
905910
VisitNamedDecl(D);
906911
JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class");

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,3 +2388,11 @@ void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
23882388
if (S->hasStoredFPFeatures())
23892389
printFPOptions(S->getStoredFPFeatures());
23902390
}
2391+
2392+
void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
2393+
if (D->isCBuffer())
2394+
OS << " cbuffer";
2395+
else
2396+
OS << " tbuffer";
2397+
dumpName(D);
2398+
}

clang/lib/Basic/IdentifierTable.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ namespace {
109109
KEYMSCOMPAT = 0x400000,
110110
KEYSYCL = 0x800000,
111111
KEYCUDA = 0x1000000,
112-
KEYMAX = KEYCUDA, // The maximum key
112+
KEYHLSL = 0x2000000,
113+
KEYMAX = KEYHLSL, // The maximum key
113114
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
114115
KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
115116
~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
@@ -199,6 +200,8 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
199200
return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
200201
case KEYCUDA:
201202
return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
203+
case KEYHLSL:
204+
return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
202205
case KEYNOCXX:
203206
// This is enabled in all non-C++ modes, but might be enabled for other
204207
// reasons as well.

clang/lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,11 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
17871787
}
17881788
return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
17891789
true, nullptr, DeclSpecStart);
1790+
1791+
case tok::kw_cbuffer:
1792+
case tok::kw_tbuffer:
1793+
SingleDecl = ParseHLSLBuffer(DeclEnd);
1794+
break;
17901795
case tok::kw_namespace:
17911796
ProhibitAttributes(DeclAttrs);
17921797
ProhibitAttributes(DeclSpecAttrs);

0 commit comments

Comments
 (0)