252 lines
9.9 KiB
C++
252 lines
9.9 KiB
C++
//===--- 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/AST/Expr.h"
|
|
#include "clang/Basic/DiagnosticParse.h"
|
|
#include "clang/Lex/LexHLSLRootSignature.h"
|
|
#include "clang/Lex/Preprocessor.h"
|
|
#include "clang/Sema/SemaHLSL.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(llvm::dxbc::RootSignatureVersion Version,
|
|
StringLiteral *Signature, 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();
|
|
|
|
/// Return all elements that have been parsed.
|
|
ArrayRef<RootSignatureElement> getElements() { return Elements; }
|
|
|
|
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(RootSignatureToken::Kind)) {
|
|
// auto ParsedObject = parse.*();
|
|
// if (!ParsedObject.has_value())
|
|
// return std::nullopt;
|
|
// ...
|
|
// }
|
|
//
|
|
// or,
|
|
//
|
|
// if (consumeExpectedToken(RootSignatureToken::Kind, ...))
|
|
// return std::nullopt;
|
|
// auto ParsedObject = parse.*();
|
|
// if (!ParsedObject.has_value())
|
|
// return std::nullopt;
|
|
// ...
|
|
//
|
|
// - All methods return std::nullopt 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:
|
|
std::optional<llvm::dxbc::RootFlags> parseRootFlags();
|
|
std::optional<llvm::hlsl::rootsig::RootConstants> parseRootConstants();
|
|
std::optional<llvm::hlsl::rootsig::RootDescriptor> parseRootDescriptor();
|
|
std::optional<llvm::hlsl::rootsig::DescriptorTable> parseDescriptorTable();
|
|
std::optional<llvm::hlsl::rootsig::DescriptorTableClause>
|
|
parseDescriptorTableClause();
|
|
std::optional<llvm::hlsl::rootsig::StaticSampler> parseStaticSampler();
|
|
|
|
/// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
|
|
/// order and only exactly once. The following methods define a
|
|
/// `Parsed.*Params` struct to denote the current state of parsed params
|
|
struct ParsedConstantParams {
|
|
std::optional<llvm::hlsl::rootsig::Register> Reg;
|
|
std::optional<uint32_t> Num32BitConstants;
|
|
std::optional<uint32_t> Space;
|
|
std::optional<llvm::dxbc::ShaderVisibility> Visibility;
|
|
};
|
|
std::optional<ParsedConstantParams> parseRootConstantParams();
|
|
|
|
struct ParsedRootDescriptorParams {
|
|
std::optional<llvm::hlsl::rootsig::Register> Reg;
|
|
std::optional<uint32_t> Space;
|
|
std::optional<llvm::dxbc::ShaderVisibility> Visibility;
|
|
std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
|
|
};
|
|
std::optional<ParsedRootDescriptorParams>
|
|
parseRootDescriptorParams(RootSignatureToken::Kind DescKind,
|
|
RootSignatureToken::Kind RegType);
|
|
|
|
struct ParsedClauseParams {
|
|
std::optional<llvm::hlsl::rootsig::Register> Reg;
|
|
std::optional<uint32_t> NumDescriptors;
|
|
std::optional<uint32_t> Space;
|
|
std::optional<uint32_t> Offset;
|
|
std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
|
|
};
|
|
std::optional<ParsedClauseParams>
|
|
parseDescriptorTableClauseParams(RootSignatureToken::Kind ClauseKind,
|
|
RootSignatureToken::Kind RegType);
|
|
|
|
struct ParsedStaticSamplerParams {
|
|
std::optional<llvm::hlsl::rootsig::Register> Reg;
|
|
std::optional<llvm::dxbc::SamplerFilter> Filter;
|
|
std::optional<llvm::dxbc::TextureAddressMode> AddressU;
|
|
std::optional<llvm::dxbc::TextureAddressMode> AddressV;
|
|
std::optional<llvm::dxbc::TextureAddressMode> AddressW;
|
|
std::optional<float> MipLODBias;
|
|
std::optional<uint32_t> MaxAnisotropy;
|
|
std::optional<llvm::dxbc::ComparisonFunc> CompFunc;
|
|
std::optional<llvm::dxbc::StaticBorderColor> BorderColor;
|
|
std::optional<float> MinLOD;
|
|
std::optional<float> MaxLOD;
|
|
std::optional<uint32_t> Space;
|
|
std::optional<llvm::dxbc::ShaderVisibility> Visibility;
|
|
std::optional<llvm::dxbc::StaticSamplerFlags> Flags;
|
|
};
|
|
std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams();
|
|
|
|
// Common parsing methods
|
|
std::optional<uint32_t> parseUIntParam();
|
|
std::optional<llvm::hlsl::rootsig::Register> parseRegister();
|
|
std::optional<float> parseFloatParam();
|
|
|
|
/// Parsing methods of various enums
|
|
std::optional<llvm::dxbc::ShaderVisibility>
|
|
parseShaderVisibility(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::SamplerFilter>
|
|
parseSamplerFilter(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::TextureAddressMode>
|
|
parseTextureAddressMode(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::ComparisonFunc>
|
|
parseComparisonFunc(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::StaticBorderColor>
|
|
parseStaticBorderColor(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::RootDescriptorFlags>
|
|
parseRootDescriptorFlags(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::DescriptorRangeFlags>
|
|
parseDescriptorRangeFlags(RootSignatureToken::Kind Context);
|
|
std::optional<llvm::dxbc::StaticSamplerFlags>
|
|
parseStaticSamplerFlags(RootSignatureToken::Kind Context);
|
|
|
|
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
|
|
/// 32-bit integer
|
|
std::optional<uint32_t> handleUIntLiteral();
|
|
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a signed
|
|
/// 32-bit integer
|
|
std::optional<int32_t> handleIntLiteral(bool Negated);
|
|
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a float
|
|
///
|
|
/// This matches the behaviour of DXC, which is as follows:
|
|
/// - convert the spelling with `strtod`
|
|
/// - check for a float overflow
|
|
/// - cast the double to a float
|
|
/// The behaviour of `strtod` is replicated using:
|
|
/// Semantics: llvm::APFloat::Semantics::S_IEEEdouble
|
|
/// RoundingMode: llvm::RoundingMode::NearestTiesToEven
|
|
std::optional<float> handleFloatLiteral(bool Negated);
|
|
|
|
/// Flags may specify the value of '0' to denote that there should be no
|
|
/// flags set.
|
|
///
|
|
/// Return true if the current int_literal token is '0', otherwise false
|
|
bool verifyZeroFlag();
|
|
|
|
/// 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(RootSignatureToken::Kind Expected);
|
|
bool peekExpectedToken(ArrayRef<RootSignatureToken::Kind> 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(
|
|
RootSignatureToken::Kind Expected, unsigned DiagID = diag::err_expected,
|
|
RootSignatureToken::Kind Context = RootSignatureToken::Kind::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(RootSignatureToken::Kind Expected);
|
|
bool tryConsumeExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
|
|
|
|
/// Consume tokens until the expected token has been peeked to be next
|
|
/// or we have reached the end of the stream. Note that this means the
|
|
/// expected token will be the next token not CurToken.
|
|
///
|
|
/// Returns true if it found a token of the given type.
|
|
bool skipUntilExpectedToken(RootSignatureToken::Kind Expected);
|
|
bool skipUntilExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
|
|
|
|
/// Consume tokens until we reach a closing right paren, ')', or, until we
|
|
/// have reached the end of the stream. This will place the current token
|
|
/// to be the end of stream or the right paren.
|
|
///
|
|
/// Returns true if it is closed before the end of stream.
|
|
bool skipUntilClosedParens(uint32_t NumParens = 1);
|
|
|
|
/// Convert the token's offset in the signature string to its SourceLocation
|
|
///
|
|
/// This allows to currently retrieve the location for multi-token
|
|
/// StringLiterals
|
|
SourceLocation getTokenLocation(RootSignatureToken Tok);
|
|
|
|
/// Construct a diagnostics at the location of the current token
|
|
DiagnosticBuilder reportDiag(unsigned DiagID) {
|
|
return getDiags().Report(getTokenLocation(CurToken), DiagID);
|
|
}
|
|
|
|
private:
|
|
llvm::dxbc::RootSignatureVersion Version;
|
|
SmallVector<RootSignatureElement> Elements;
|
|
StringLiteral *Signature;
|
|
RootSignatureLexer Lexer;
|
|
Preprocessor &PP;
|
|
|
|
RootSignatureToken CurToken;
|
|
};
|
|
|
|
IdentifierInfo *ParseHLSLRootSignature(Sema &Actions,
|
|
llvm::dxbc::RootSignatureVersion Version,
|
|
StringLiteral *Signature);
|
|
|
|
void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig);
|
|
|
|
} // namespace hlsl
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H
|