Skip to content

Commit 9be00bd

Browse files
committed
add support for parsing signed integer for float param
1 parent f3ace33 commit 9be00bd

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class RootSignatureParser {
118118
// Common parsing methods
119119
std::optional<uint32_t> parseUIntParam();
120120
std::optional<llvm::hlsl::rootsig::Register> parseRegister();
121+
std::optional<float> parseFloatParam();
121122

122123
/// Parsing methods of various enums
123124
std::optional<llvm::hlsl::rootsig::ShaderVisibility> parseShaderVisibility();
@@ -129,6 +130,9 @@ class RootSignatureParser {
129130
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
130131
/// 32-bit integer
131132
std::optional<uint32_t> handleUIntLiteral();
133+
/// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
134+
/// 32-bit integer
135+
std::optional<int32_t> handleIntLiteral(bool Negated);
132136

133137
/// Flags may specify the value of '0' to denote that there should be no
134138
/// flags set.

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ RootSignatureParser::parseStaticSamplerParams() {
677677
if (consumeExpectedToken(TokenKind::pu_equal))
678678
return std::nullopt;
679679

680-
auto MipLODBias = parseUIntParam();
680+
auto MipLODBias = parseFloatParam();
681681
if (!MipLODBias.has_value())
682682
return std::nullopt;
683683
Params.MipLODBias = (float)*MipLODBias;
@@ -730,6 +730,30 @@ std::optional<Register> RootSignatureParser::parseRegister() {
730730
return Reg;
731731
}
732732

733+
std::optional<float> RootSignatureParser::parseFloatParam() {
734+
assert(CurToken.TokKind == TokenKind::pu_equal &&
735+
"Expects to only be invoked starting at given keyword");
736+
// Consume sign modifier
737+
bool Signed = tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
738+
bool Negated = Signed && CurToken.TokKind == TokenKind::pu_minus;
739+
740+
// Handle an uint and interpret it as a float
741+
if (!Signed && tryConsumeExpectedToken(TokenKind::int_literal)) {
742+
auto UInt = handleUIntLiteral();
743+
if (!UInt.has_value())
744+
return std::nullopt;
745+
return (float)UInt.value();
746+
} else if (tryConsumeExpectedToken(TokenKind::int_literal)) {
747+
auto Int = handleIntLiteral(Negated);
748+
if (!Int.has_value())
749+
return std::nullopt;
750+
751+
return (float)Int.value();
752+
}
753+
754+
return std::nullopt;
755+
}
756+
733757
std::optional<llvm::hlsl::rootsig::ShaderVisibility>
734758
RootSignatureParser::parseShaderVisibility() {
735759
assert(CurToken.TokKind == TokenKind::pu_equal &&
@@ -856,6 +880,31 @@ std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
856880
return Val.getExtValue();
857881
}
858882

883+
std::optional<int32_t> RootSignatureParser::handleIntLiteral(bool Negated) {
884+
// Parse the numeric value and do semantic checks on its specification
885+
clang::NumericLiteralParser Literal(CurToken.NumSpelling, CurToken.TokLoc,
886+
PP.getSourceManager(), PP.getLangOpts(),
887+
PP.getTargetInfo(), PP.getDiagnostics());
888+
if (Literal.hadError)
889+
return true; // Error has already been reported so just return
890+
891+
assert(Literal.isIntegerLiteral() && "IsNumberChar will only support digits");
892+
893+
llvm::APSInt Val = llvm::APSInt(32, true);
894+
if (Literal.GetIntegerValue(Val) || INT32_MAX < Val.getExtValue()) {
895+
// Report that the value has overflowed
896+
PP.getDiagnostics().Report(CurToken.TokLoc,
897+
diag::err_hlsl_number_literal_overflow)
898+
<< 0 << CurToken.NumSpelling;
899+
return std::nullopt;
900+
}
901+
902+
if (Negated)
903+
return static_cast<int32_t>((-Val).getExtValue());
904+
905+
return static_cast<int32_t>(Val.getExtValue());
906+
}
907+
859908
bool RootSignatureParser::verifyZeroFlag() {
860909
assert(CurToken.TokKind == TokenKind::int_literal);
861910
auto X = handleUIntLiteral();

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,42 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
247247
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
248248
ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.ViewType, RegisterType::SReg);
249249
ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.Number, 0u);
250-
ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0u);
250+
ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0.f);
251+
252+
ASSERT_TRUE(Consumer->isSatisfied());
253+
}
254+
255+
TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) {
256+
const llvm::StringLiteral Source = R"cc(
257+
StaticSampler(s0, mipLODBias = 0),
258+
StaticSampler(s0, mipLODBias = +1),
259+
StaticSampler(s0, mipLODBias = -1)
260+
)cc";
261+
262+
TrivialModuleLoader ModLoader;
263+
auto PP = createPP(Source, ModLoader);
264+
auto TokLoc = SourceLocation();
265+
266+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
267+
SmallVector<RootElement> Elements;
268+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
269+
270+
// Test no diagnostics produced
271+
Consumer->setNoDiag();
272+
273+
ASSERT_FALSE(Parser.parse());
274+
275+
RootElement Elem = Elements[0];
276+
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
277+
ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0.f);
278+
279+
Elem = Elements[1];
280+
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
281+
ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 1.f);
282+
283+
Elem = Elements[2];
284+
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
285+
ASSERT_EQ(std::get<StaticSampler>(Elem).MipLODBias, -1.f);
251286

252287
ASSERT_TRUE(Consumer->isSatisfied());
253288
}

0 commit comments

Comments
 (0)