[clang] [HLSL][RootSignature] Implement Lexing of DescriptorTables (PR #122981)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 9 13:10:13 PST 2025
================
@@ -0,0 +1,151 @@
+#include "clang/Parse/ParseHLSLRootSignature.h"
+
+namespace llvm {
+namespace hlsl {
+namespace root_signature {
+
+// Lexer Definitions
+
+static bool IsPreprocessorNumberChar(char C) {
+ // TODO: extend for float support with or without hexadecimal/exponent
+ return isdigit(C); // integer support
+}
+
+bool RootSignatureLexer::LexNumber(RootSignatureToken &Result) {
+ // NumericLiteralParser does not handle the sign so we will manually apply it
+ Result.Signed = Buffer.front() == '-';
+ if (Result.Signed)
+ AdvanceBuffer();
+
+ // Retrieve the possible number
+ StringRef NumSpelling = Buffer.take_while(IsPreprocessorNumberChar);
+
+ // Parse the numeric value and so semantic checks on its specification
+ clang::NumericLiteralParser Literal(NumSpelling, SourceLoc,
+ PP.getSourceManager(), PP.getLangOpts(),
+ PP.getTargetInfo(), PP.getDiagnostics());
+ if (Literal.hadError)
+ return true; // Error has already been reported so just return
+
+ // Retrieve the number value to store into the token
+ if (Literal.isIntegerLiteral()) {
+ Result.Kind = TokenKind::int_literal;
+
+ APSInt X = APSInt(32, Result.Signed);
+ if (Literal.GetIntegerValue(X))
+ return true; // TODO: Report overflow error
+
+ X = Result.Signed ? -X : X;
+ Result.IntLiteral = (uint32_t)X.getZExtValue();
+ } else {
+ return true; // TODO: report unsupported number literal specification
+ }
+
+ AdvanceBuffer(NumSpelling.size());
+ return false;
+}
+
+bool RootSignatureLexer::Lex(SmallVector<RootSignatureToken> &Tokens) {
+ // Discard any leading whitespace
+ AdvanceBuffer(Buffer.take_while(isspace).size());
+
+ while (!Buffer.empty()) {
+ RootSignatureToken Result;
+ if (LexToken(Result))
+ return true;
+
+ // Successfully Lexed the token so we can store it
+ Tokens.push_back(Result);
+
+ // Discard any trailing whitespace
+ AdvanceBuffer(Buffer.take_while(isspace).size());
+ }
+
+ return false;
+}
+
+bool RootSignatureLexer::LexToken(RootSignatureToken &Result) {
+ // Record where this token is in the text for usage in parser diagnostics
+ Result.TokLoc = SourceLoc;
+
+ char C = Buffer.front();
+
+ // Punctuators
+ switch (C) {
+#define PUNCTUATOR(X, Y) \
+ case Y: { \
+ Result.Kind = TokenKind::pu_##X; \
+ AdvanceBuffer(); \
+ return false; \
+ }
+#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
+ default:
+ break;
+ }
+
+ // Numeric constant
+ if (isdigit(C) || C == '-')
+ return LexNumber(Result);
+
+ // All following tokens require at least one additional character
+ if (Buffer.size() <= 1)
+ return true; // TODO: Report invalid token error
+
+ // Peek at the next character to deteremine token type
+ char NextC = Buffer[1];
+
+ // Registers: [tsub][0-9+]
+ if ((C == 't' || C == 's' || C == 'u' || C == 'b') && isdigit(NextC)) {
+ AdvanceBuffer();
+
+ if (LexNumber(Result))
+ return true;
+
+ // Lex number could also parse a float so ensure it was an unsigned int
+ if (Result.Kind != TokenKind::int_literal || Result.Signed)
+ return true; // Return invalid number literal for register error
+
+ // Convert character to the register type.
+ // This is done after LexNumber to override the TokenKind
+ switch (C) {
+ case 'b':
+ Result.Kind = TokenKind::bReg;
+ break;
+ case 't':
+ Result.Kind = TokenKind::tReg;
+ break;
+ case 'u':
+ Result.Kind = TokenKind::uReg;
+ break;
+ case 's':
+ Result.Kind = TokenKind::sReg;
+ break;
+ default:
+ llvm_unreachable("Switch for an expected token was not provided");
+ return true;
+ }
+ return false;
+ }
+
+ // Keywords and Enums:
----------------
llvm-beanz wrote:
I definitely prefer starting with the simple approach and only going complicated if we need to. DXC had a bunch of hand-rolled string matching functions that unrolled the strings... and a few of them had some bad bugs. So this is the perfect way to start.
https://github.com/llvm/llvm-project/pull/122981
More information about the cfe-commits
mailing list