ParseHLSL.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //===--- ParseHLSL.cpp - HLSL Parsing -------------------------------------===//
  2. ///////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // ParseHLSL.cpp //
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. // This file is distributed under the University of Illinois Open Source //
  7. // License. See LICENSE.TXT for details. //
  8. // //
  9. // This file implements the HLSLportions of the Parser interfaces. //
  10. // //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "clang/Parse/Parser.h"
  13. #include "RAIIObjectsForParser.h"
  14. #include "clang/Basic/CharInfo.h"
  15. #include "clang/Basic/OperatorKinds.h"
  16. #include "clang/AST/ASTContext.h"
  17. #include "clang/AST/DeclTemplate.h"
  18. #include "clang/Parse/ParseDiagnostic.h"
  19. #include "clang/Sema/DeclSpec.h"
  20. #include "clang/Sema/ParsedTemplate.h"
  21. #include "clang/Sema/PrettyDeclStackTrace.h"
  22. #include "clang/Sema/Scope.h"
  23. #include "clang/Sema/SemaDiagnostic.h"
  24. #include "llvm/ADT/SmallString.h"
  25. using namespace clang;
  26. Decl *Parser::ParseCTBuffer(unsigned Context, SourceLocation &DeclEnd,
  27. ParsedAttributesWithRange &CTBAttrs,
  28. SourceLocation InlineLoc) {
  29. assert((Tok.is(tok::kw_cbuffer) || Tok.is(tok::kw_tbuffer)) &&
  30. "Not a cbuffer or tbuffer!");
  31. bool isCBuffer = Tok.is(tok::kw_cbuffer);
  32. SourceLocation BufferLoc = ConsumeToken(); // eat the 'cbuffer or tbuffer'.
  33. if (!Tok.is(tok::identifier)) {
  34. Diag(Tok, diag::err_expected) << tok::identifier;
  35. return nullptr;
  36. }
  37. IdentifierInfo *identifier = Tok.getIdentifierInfo();
  38. SourceLocation identifierLoc = ConsumeToken(); // consume identifier
  39. std::vector<hlsl::UnusualAnnotation *> hlslAttrs;
  40. MaybeParseHLSLAttributes(hlslAttrs);
  41. ParseScope BufferScope(this, Scope::DeclScope);
  42. BalancedDelimiterTracker T(*this, tok::l_brace);
  43. if (T.consumeOpen()) {
  44. Diag(Tok, diag::err_expected) << tok::l_brace;
  45. return nullptr;
  46. }
  47. Decl *decl = Actions.ActOnStartHLSLBuffer(getCurScope(), isCBuffer, BufferLoc,
  48. identifier, identifierLoc,
  49. hlslAttrs, T.getOpenLocation());
  50. // Process potential C++11 attribute specifiers
  51. Actions.ProcessDeclAttributeList(getCurScope(), decl, CTBAttrs.getList());
  52. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
  53. ParsedAttributesWithRange attrs(AttrFactory);
  54. MaybeParseCXX11Attributes(attrs);
  55. MaybeParseHLSLAttributes(attrs);
  56. MaybeParseMicrosoftAttributes(attrs);
  57. ParseExternalDeclaration(attrs);
  58. }
  59. T.consumeClose();
  60. DeclEnd = T.getCloseLocation();
  61. BufferScope.Exit();
  62. Actions.ActOnFinishHLSLBuffer(decl, DeclEnd);
  63. return decl;
  64. }
  65. Decl *Parser::ParseConstBuffer(unsigned Context, SourceLocation &DeclEnd,
  66. ParsedAttributesWithRange &attrs,
  67. SourceLocation InlineLoc) {
  68. bool isCBuffer = Tok.is(tok::kw_ConstantBuffer);
  69. assert((isCBuffer || Tok.is(tok::kw_TextureBuffer)) && "Not a ConstantBuffer or TextureBuffer!");
  70. SourceLocation BufferLoc = ConsumeToken(); // eat the 'ConstantBuffer'.
  71. if (!Tok.is(tok::less)) {
  72. Diag(Tok, diag::err_expected) << tok::less;
  73. return nullptr;
  74. }
  75. ConsumeToken(); // eat the <
  76. ParsingDeclSpec PDS(*this);
  77. ParseDeclarationSpecifiers(PDS);
  78. if (!Tok.is(tok::greater)) {
  79. Diag(Tok, diag::err_expected) << tok::greater;
  80. return nullptr;
  81. }
  82. ConsumeToken(); // eat the >
  83. PDS.takeAttributesFrom(attrs);
  84. Actions.ActOnStartHLSLBufferView();
  85. Parser::DeclGroupPtrTy dcl = ParseDeclGroup(PDS, Declarator::FileContext);
  86. // If parsing of decl group fails, then decl group must have been illformed. Bail out!
  87. // Note that we don't have to generate any diagnostics here as it was already
  88. // generated previously in ParseDirectDeclarator().
  89. if (!dcl)
  90. return nullptr;
  91. // Check if the register type is valid
  92. NamedDecl *namedDecl = cast<NamedDecl>(dcl.get().getSingleDecl());
  93. ArrayRef<hlsl::UnusualAnnotation*> annotations = namedDecl->getUnusualAnnotations();
  94. for (hlsl::UnusualAnnotation* annotation : annotations) {
  95. if (const auto *regAssignment = dyn_cast<hlsl::RegisterAssignment>(annotation)) {
  96. if (regAssignment->isSpaceOnly())
  97. continue;
  98. if (isCBuffer && regAssignment->RegisterType != 'b' && regAssignment->RegisterType != 'B') {
  99. Diag(namedDecl->getLocation(), diag::err_hlsl_incorrect_bind_semantic) << "'b'";
  100. }
  101. else if (!isCBuffer && regAssignment->RegisterType != 't' && regAssignment->RegisterType != 'T') {
  102. Diag(namedDecl->getLocation(), diag::err_hlsl_incorrect_bind_semantic) << "'t'";
  103. }
  104. }
  105. }
  106. Decl *decl = Actions.ActOnHLSLBufferView(getCurScope(), BufferLoc, dcl, isCBuffer);
  107. return decl;
  108. }
  109. /// ParseHLSLAttributeSpecifier - Parse an HLSL attribute-specifier.
  110. ///
  111. /// [HLSL] attribute-specifier:
  112. /// '[' attribute[opt] ']'
  113. ///
  114. /// [HLSL] attribute:
  115. /// attribute-token attribute-argument-clause[opt]
  116. ///
  117. /// [HLSL] attribute-token:
  118. /// identifier
  119. ///
  120. /// [HLSL] attribute-argument-clause:
  121. /// '(' attribute-params ')'
  122. ///
  123. /// [HLSL] attribute-params:
  124. /// constant-expr
  125. /// attribute-params ',' constant-expr
  126. ///
  127. void Parser::ParseHLSLAttributeSpecifier(ParsedAttributes &attrs,
  128. SourceLocation *endLoc) {
  129. assert(getLangOpts().HLSL);
  130. assert(Tok.is(tok::l_square) && "Not an HLSL attribute list");
  131. ConsumeBracket();
  132. llvm::SmallDenseMap<IdentifierInfo *, SourceLocation, 4> SeenAttrs;
  133. // '[]' is valid.
  134. if (Tok.is(tok::r_square)) {
  135. *endLoc = ConsumeBracket();
  136. return;
  137. }
  138. if (!Tok.isAnyIdentifier()) {
  139. Diag(Tok, diag::err_expected) << tok::identifier;
  140. SkipUntil(tok::r_square);
  141. return;
  142. }
  143. SourceLocation AttrLoc;
  144. IdentifierInfo *AttrName = 0;
  145. AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
  146. assert(AttrName != nullptr && "already called isAnyIdenfier before");
  147. // Parse attribute arguments
  148. if (Tok.is(tok::l_paren)) {
  149. if (AttrName == &this->Actions.getASTContext().Idents.get("clipplanes")) {
  150. ArgsVector ArgExprs;
  151. ConsumeParen();
  152. for (;;) {
  153. ExprResult ArgExpr(ParseAssignmentExpression());
  154. if (ArgExpr.isInvalid()) {
  155. SkipUntil(tok::r_paren, StopAtSemi);
  156. return;
  157. }
  158. ArgExprs.push_back(ArgExpr.get());
  159. // Consume a comma and process the next argument.
  160. if (!Tok.is(tok::comma)) {
  161. break;
  162. }
  163. ConsumeToken();
  164. }
  165. SourceLocation EndLoc = Tok.getLocation();
  166. if (ExpectAndConsume(tok::r_paren, diag::err_expected))
  167. SkipUntil(tok::r_paren);
  168. attrs.addNew(AttrName, SourceRange(AttrLoc, EndLoc), nullptr,
  169. SourceLocation(), ArgExprs.data(), ArgExprs.size(),
  170. AttributeList::AS_CXX11);
  171. } else {
  172. ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc, nullptr,
  173. SourceLocation(), AttributeList::AS_CXX11, nullptr);
  174. }
  175. } else {
  176. attrs.addNew(AttrName, AttrLoc, nullptr, SourceLocation(), 0, 0,
  177. AttributeList::AS_CXX11);
  178. }
  179. if (endLoc)
  180. *endLoc = Tok.getLocation();
  181. if (ExpectAndConsume(tok::r_square, diag::err_expected))
  182. SkipUntil(tok::r_square);
  183. }
  184. /// ParseHLSLAttributes - Parse an HLSL attribute-specifier-seq.
  185. ///
  186. /// attribute-specifier-seq:
  187. /// attribute-specifier-seq[opt] attribute-specifier
  188. void Parser::ParseHLSLAttributes(ParsedAttributesWithRange &attrs,
  189. SourceLocation *endLoc) {
  190. assert(getLangOpts().HLSL);
  191. SourceLocation StartLoc = Tok.getLocation(), Loc;
  192. if (!endLoc)
  193. endLoc = &Loc;
  194. do {
  195. ParseHLSLAttributeSpecifier(attrs, endLoc);
  196. } while (Tok.is(tok::l_square));
  197. attrs.Range = SourceRange(StartLoc, *endLoc);
  198. }