-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[HLSL][RootSignature] Implement parsing of a DescriptorTable with empty clauses #133302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
3094705
[NFC][HLSL][RootSignature] add spelling of tokens to tokenkind.def
inbelic d744cd1
[HLSL][RootSignature] Implement parsing of an empty DescriptorTable
a0999c7
implement parsing of empty DescriptorTableClause
14c0479
self-review: docs
9f07795
review: clang-format
49cc48e
self-review: fix up comment
d87707f
review: fix build issue on api change
d944fff
review: return true from case
2123282
review: use unreachable
318f1ec
review: conform to llvm method naming conventions
2af4de6
review: use llvm::is_contained instead of custom function
78c3837
review: typos
262eeed
review: remove api of `consumeExpectedToken` for multiple token kinds
2eeda54
self-review: improve error messaging for expected end of parameters
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
//===--- ParseHLSLRootSignature.h -------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file defines the RootSignatureParser interface. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H | ||
#define LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H | ||
|
||
#include "clang/Basic/DiagnosticParse.h" | ||
#include "clang/Lex/LexHLSLRootSignature.h" | ||
#include "clang/Lex/Preprocessor.h" | ||
|
||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/ADT/StringRef.h" | ||
|
||
#include "llvm/Frontend/HLSL/HLSLRootSignature.h" | ||
|
||
namespace clang { | ||
namespace hlsl { | ||
|
||
class RootSignatureParser { | ||
public: | ||
RootSignatureParser(SmallVector<llvm::hlsl::rootsig::RootElement> &Elements, | ||
RootSignatureLexer &Lexer, clang::Preprocessor &PP); | ||
|
||
/// Consumes tokens from the Lexer and constructs the in-memory | ||
/// representations of the RootElements. Tokens are consumed until an | ||
/// error is encountered or the end of the buffer. | ||
/// | ||
/// Returns true if a parsing error is encountered. | ||
bool parse(); | ||
|
||
private: | ||
DiagnosticsEngine &getDiags() { return PP.getDiagnostics(); } | ||
|
||
// All private Parse.* methods follow a similar pattern: | ||
// - Each method will start with an assert to denote what the CurToken is | ||
// expected to be and will parse from that token forward | ||
// | ||
// - Therefore, it is the callers responsibility to ensure that you are | ||
// at the correct CurToken. This should be done with the pattern of: | ||
// | ||
// if (TryConsumeExpectedToken(TokenKind)) | ||
// if (Parse.*()) | ||
// return true; | ||
// | ||
// or, | ||
// | ||
// if (ConsumeExpectedToken(TokenKind, ...)) | ||
// return true; | ||
// if (Parse.*()) | ||
// return true; | ||
// | ||
// - All methods return true if a parsing error is encountered. It is the | ||
// callers responsibility to propogate this error up, or deal with it | ||
// otherwise | ||
// | ||
// - An error will be raised if the proceeding tokens are not what is | ||
// expected, or, there is a lexing error | ||
|
||
/// Root Element parse methods: | ||
bool parseDescriptorTable(); | ||
bool parseDescriptorTableClause(); | ||
|
||
/// Invoke the Lexer to consume a token and update CurToken with the result | ||
void consumeNextToken() { CurToken = Lexer.ConsumeToken(); } | ||
|
||
/// Return true if the next token one of the expected kinds | ||
bool peekExpectedToken(TokenKind Expected); | ||
bool peekExpectedToken(ArrayRef<TokenKind> AnyExpected); | ||
|
||
/// Consumes the next token and report an error if it is not of the expected | ||
/// kind. | ||
/// | ||
/// Returns true if there was an error reported. | ||
bool consumeExpectedToken(TokenKind Expected, | ||
unsigned DiagID = diag::err_expected, | ||
TokenKind Context = TokenKind::invalid); | ||
|
||
/// Peek if the next token is of the expected kind and if it is then consume | ||
/// it. | ||
/// | ||
/// Returns true if it successfully matches the expected kind and the token | ||
/// was consumed. | ||
bool tryConsumeExpectedToken(TokenKind Expected); | ||
bool tryConsumeExpectedToken(ArrayRef<TokenKind> Expected); | ||
|
||
private: | ||
SmallVector<llvm::hlsl::rootsig::RootElement> &Elements; | ||
RootSignatureLexer &Lexer; | ||
|
||
clang::Preprocessor &PP; | ||
|
||
RootSignatureToken CurToken; | ||
}; | ||
|
||
} // namespace hlsl | ||
} // namespace clang | ||
|
||
#endif // LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inbelic marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
//=== ParseHLSLRootSignature.cpp - Parse Root Signature -------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "clang/Parse/ParseHLSLRootSignature.h" | ||
|
||
#include "llvm/Support/raw_ostream.h" | ||
|
||
using namespace llvm::hlsl::rootsig; | ||
|
||
namespace clang { | ||
namespace hlsl { | ||
|
||
RootSignatureParser::RootSignatureParser(SmallVector<RootElement> &Elements, | ||
RootSignatureLexer &Lexer, | ||
Preprocessor &PP) | ||
: Elements(Elements), Lexer(Lexer), PP(PP), CurToken(SourceLocation()) {} | ||
|
||
bool RootSignatureParser::parse() { | ||
// Iterate as many RootElements as possible | ||
while (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) { | ||
// Dispatch onto parser method. | ||
// We guard against the unreachable here as we just ensured that CurToken | ||
// will be one of the kinds in the while condition | ||
switch (CurToken.Kind) { | ||
case TokenKind::kw_DescriptorTable: | ||
if (parseDescriptorTable()) | ||
return true; | ||
break; | ||
default: | ||
llvm_unreachable("Switch for consumed token was not provided"); | ||
} | ||
|
||
if (!tryConsumeExpectedToken(TokenKind::pu_comma)) | ||
break; | ||
} | ||
|
||
if (!tryConsumeExpectedToken(TokenKind::end_of_stream)) { | ||
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_unexpected_end_of_params) | ||
<< /*expected=*/TokenKind::end_of_stream | ||
<< /*param of=*/TokenKind::kw_RootSignature; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
bool RootSignatureParser::parseDescriptorTable() { | ||
assert(CurToken.Kind == TokenKind::kw_DescriptorTable && | ||
"Expects to only be invoked starting at given keyword"); | ||
|
||
DescriptorTable Table; | ||
|
||
if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after, | ||
CurToken.Kind)) | ||
return true; | ||
|
||
// Iterate as many Clauses as possible | ||
while (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV, | ||
TokenKind::kw_UAV, TokenKind::kw_Sampler})) { | ||
if (parseDescriptorTableClause()) | ||
return true; | ||
|
||
Table.NumClauses++; | ||
|
||
if (!tryConsumeExpectedToken(TokenKind::pu_comma)) | ||
break; | ||
} | ||
|
||
if (!tryConsumeExpectedToken(TokenKind::pu_r_paren)) { | ||
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_unexpected_end_of_params) | ||
<< /*expected=*/TokenKind::pu_r_paren | ||
<< /*param of=*/TokenKind::kw_DescriptorTable; | ||
return true; | ||
} | ||
|
||
Elements.push_back(Table); | ||
return false; | ||
} | ||
|
||
bool RootSignatureParser::parseDescriptorTableClause() { | ||
assert((CurToken.Kind == TokenKind::kw_CBV || | ||
CurToken.Kind == TokenKind::kw_SRV || | ||
CurToken.Kind == TokenKind::kw_UAV || | ||
CurToken.Kind == TokenKind::kw_Sampler) && | ||
"Expects to only be invoked starting at given keyword"); | ||
|
||
DescriptorTableClause Clause; | ||
switch (CurToken.Kind) { | ||
default: | ||
llvm_unreachable("Switch for consumed token was not provided"); | ||
case TokenKind::kw_CBV: | ||
Clause.Type = ClauseType::CBuffer; | ||
break; | ||
case TokenKind::kw_SRV: | ||
Clause.Type = ClauseType::SRV; | ||
break; | ||
case TokenKind::kw_UAV: | ||
Clause.Type = ClauseType::UAV; | ||
break; | ||
case TokenKind::kw_Sampler: | ||
Clause.Type = ClauseType::Sampler; | ||
break; | ||
} | ||
|
||
if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after, | ||
CurToken.Kind)) | ||
return true; | ||
|
||
if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_after, | ||
CurToken.Kind)) | ||
return true; | ||
|
||
Elements.push_back(Clause); | ||
return false; | ||
} | ||
|
||
bool RootSignatureParser::peekExpectedToken(TokenKind Expected) { | ||
return peekExpectedToken(ArrayRef{Expected}); | ||
} | ||
|
||
bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) { | ||
RootSignatureToken Result = Lexer.PeekNextToken(); | ||
return llvm::is_contained(AnyExpected, Result.Kind); | ||
} | ||
|
||
bool RootSignatureParser::consumeExpectedToken(TokenKind Expected, | ||
unsigned DiagID, | ||
TokenKind Context) { | ||
if (tryConsumeExpectedToken(Expected)) | ||
return false; | ||
|
||
// Report unexpected token kind error | ||
DiagnosticBuilder DB = getDiags().Report(CurToken.TokLoc, DiagID); | ||
switch (DiagID) { | ||
case diag::err_expected: | ||
DB << Expected; | ||
break; | ||
case diag::err_expected_either: | ||
case diag::err_expected_after: | ||
DB << Expected << Context; | ||
break; | ||
default: | ||
break; | ||
} | ||
return true; | ||
} | ||
|
||
bool RootSignatureParser::tryConsumeExpectedToken(TokenKind Expected) { | ||
return tryConsumeExpectedToken(ArrayRef{Expected}); | ||
} | ||
|
||
bool RootSignatureParser::tryConsumeExpectedToken( | ||
ArrayRef<TokenKind> AnyExpected) { | ||
// If not the expected token just return | ||
if (!peekExpectedToken(AnyExpected)) | ||
return false; | ||
consumeNextToken(); | ||
return true; | ||
} | ||
|
||
} // namespace hlsl | ||
} // namespace clang |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.