Skip to content

Commit 388169b

Browse files
committed
add support for parsing signed integer for float param
1 parent f434cae commit 388169b

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
@@ -679,7 +679,7 @@ RootSignatureParser::parseStaticSamplerParams() {
679679
if (consumeExpectedToken(TokenKind::pu_equal))
680680
return std::nullopt;
681681

682-
auto MipLODBias = parseUIntParam();
682+
auto MipLODBias = parseFloatParam();
683683
if (!MipLODBias.has_value())
684684
return std::nullopt;
685685
Params.MipLODBias = (float)*MipLODBias;
@@ -732,6 +732,30 @@ std::optional<Register> RootSignatureParser::parseRegister() {
732732
return Reg;
733733
}
734734

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

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