Skip to content

Commit d741383

Browse files
committed
Add version checks for implicit types and type constants
1 parent a3e2fa6 commit d741383

File tree

8 files changed

+99
-19
lines changed

8 files changed

+99
-19
lines changed

include/NZSL/Ast/Transformations/TransformerContext.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ namespace nzsl::Ast
7979
{
8080
std::string name;
8181
std::variant<ExpressionType, PartialType> content;
82+
std::function<void(const SourceLocation& sourceLocation)> check;
8283
};
8384

8485
struct VariableData

include/NZSL/Lang/Constants.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace nzsl::Version
1616
constexpr std::uint32_t MinVersion = Build(1, 0, 0);
1717

1818
// Features
19+
constexpr std::uint32_t ImplicitTypes = Build(1, 1, 0);
20+
constexpr std::uint32_t TypeConstants = Build(1, 1, 0);
1921
constexpr std::uint32_t UntypedLiterals = Build(1, 1, 0);
2022
}
2123

include/NZSL/Lang/ErrorList.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ NZSL_SHADERLANG_COMPILER_ERROR(MissingOptionValue, "option {} requires a value (
140140
NZSL_SHADERLANG_COMPILER_ERROR(MissingWorkgroupAttribute, "compute shader requires a workgroup attribute")
141141
NZSL_SHADERLANG_COMPILER_ERROR(ModuleCompilationFailed, "module {} compilation failed: {}", std::string, std::string)
142142
NZSL_SHADERLANG_COMPILER_ERROR(ModuleFeatureMismatch, "module {} requires feature {}", std::string, Ast::ModuleFeature)
143+
NZSL_SHADERLANG_COMPILER_ERROR(ModuleFeatureNotEnabled, "using {} requires module feature {} to be enabled", std::string, Ast::ModuleFeature)
143144
NZSL_SHADERLANG_COMPILER_ERROR(ModuleNotFound, "module {} not found", std::string)
144145
NZSL_SHADERLANG_COMPILER_ERROR(MultiplePushConstant, "there can be only one push constant external in a shader stage", std::string)
145146
NZSL_SHADERLANG_COMPILER_ERROR(NoModuleResolver, "import statement found but no module resolver has been set (and partial compilation is not enabled)")
@@ -170,6 +171,7 @@ NZSL_SHADERLANG_COMPILER_ERROR(UnknownIdentifier, "unknown identifier {}", std::
170171
NZSL_SHADERLANG_COMPILER_ERROR(UnknownMethod, "type {} has no method {}", std::string, std::string)
171172
NZSL_SHADERLANG_COMPILER_ERROR(UnmatchingTypes, "left expression type ({}) doesn't match right expression type ({})", std::string, std::string)
172173
NZSL_SHADERLANG_COMPILER_ERROR(UnsupportedAttributeOnStage, "{} entry-point doesn't support {} attribute", std::string, std::string)
174+
NZSL_SHADERLANG_COMPILER_ERROR(UnsupportedFeature, "\"{}\" feature requires NZSL {} (current module version is {})", std::string, VersionTag, VersionTag)
173175
NZSL_SHADERLANG_COMPILER_ERROR(VarDeclarationMissingTypeAndValue, "variable must either have a type or an initial value")
174176
NZSL_SHADERLANG_COMPILER_ERROR(VarDeclarationOutsideOfFunction, "global variables outside of external blocks are forbidden")
175177
NZSL_SHADERLANG_COMPILER_ERROR(VarDeclarationTypeUnmatching, "initial expression type ({}) doesn't match specified type ({})", std::string, std::string)

include/NZSL/Lang/Errors.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <NZSL/Parser.hpp>
1212
#include <NZSL/Ast/Enums.hpp>
1313
#include <NZSL/Lang/SourceLocation.hpp>
14+
#include <NZSL/Lang/Version.hpp>
1415
#include <exception>
1516
#include <memory>
1617
#include <string>

include/NZSL/Lang/Version.hpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,25 @@
1111
#include <cstdint>
1212
#include <string>
1313

14-
namespace nzsl::Version
14+
namespace nzsl
1515
{
16-
// Functions
17-
constexpr std::uint32_t Build(std::uint32_t majorVersion, std::uint32_t minorVersion, std::uint32_t patchVersion);
18-
constexpr void Decompose(std::uint32_t version, std::uint32_t& majorVersion, std::uint32_t& minorVersion, std::uint32_t& patchVersion);
19-
std::string ToString(std::uint32_t version);
20-
21-
// Constants
22-
constexpr std::uint32_t MaxMajorVersion = 1u << 10;
23-
constexpr std::uint32_t MaxMinorVersion = 1u << 10;
24-
constexpr std::uint32_t MaxPatchVersion = 1u << 12;
16+
struct VersionTag
17+
{
18+
std::uint32_t version;
19+
};
20+
21+
namespace Version
22+
{
23+
// Functions
24+
constexpr std::uint32_t Build(std::uint32_t majorVersion, std::uint32_t minorVersion, std::uint32_t patchVersion);
25+
constexpr void Decompose(std::uint32_t version, std::uint32_t& majorVersion, std::uint32_t& minorVersion, std::uint32_t& patchVersion);
26+
std::string ToString(std::uint32_t version);
27+
28+
// Constants
29+
constexpr std::uint32_t MaxMajorVersion = 1u << 10;
30+
constexpr std::uint32_t MaxMinorVersion = 1u << 10;
31+
constexpr std::uint32_t MaxPatchVersion = 1u << 12;
32+
}
2533
}
2634

2735
#include <NZSL/Lang/Version.inl>

src/NZSL/Ast/Transformations/ResolveTransformer.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -614,20 +614,22 @@ namespace nzsl::Ast
614614

615615
void ResolveTransformer::RegisterBuiltin()
616616
{
617-
auto RegisterFullType = [this](std::string name, ExpressionType&& expressionType)
617+
auto RegisterFullType = [this](std::string name, ExpressionType&& expressionType, std::function<void(const SourceLocation& sourceLocation)> check = nullptr)
618618
{
619619
TransformerContext::TypeData typeData;
620620
typeData.content = std::move(expressionType);
621621
typeData.name = name;
622+
typeData.check = std::move(check);
622623

623624
RegisterType(std::move(name), std::move(typeData), std::nullopt, {});
624625
};
625626

626-
auto RegisterPartialType = [this](std::string name, PartialType&& partialType)
627+
auto RegisterPartialType = [this](std::string name, PartialType&& partialType, std::function<void(const SourceLocation& sourceLocation)> check = nullptr)
627628
{
628629
TransformerContext::TypeData typeData;
629630
typeData.content = std::move(partialType);
630631
typeData.name = name;
632+
typeData.check = std::move(check);
631633

632634
RegisterType(std::move(name), std::move(typeData), std::nullopt, {});
633635
};
@@ -638,8 +640,10 @@ namespace nzsl::Ast
638640
RegisterFullType("i32", PrimitiveType::Int32);
639641
RegisterFullType("u32", PrimitiveType::UInt32);
640642

641-
if (IsFeatureEnabled(ModuleFeature::Float64))
642-
RegisterFullType("f64", PrimitiveType::Float64);
643+
RegisterFullType("f64", PrimitiveType::Float64, IsFeatureEnabled(ModuleFeature::Float64) ? nullptr : [](const SourceLocation& sourceLocation)
644+
{
645+
throw CompilerModuleFeatureNotEnabledError{ sourceLocation, "f64", ModuleFeature::Float64 };
646+
});
643647

644648
// Partial types
645649

@@ -651,7 +655,12 @@ namespace nzsl::Ast
651655
assert(parameterCount <= 2);
652656

653657
if (parameterCount == 0)
658+
{
659+
if (m_states->currentModule->metadata->shaderLangVersion < Version::ImplicitTypes)
660+
throw CompilerUnsupportedFeatureError{ sourceLocation, "implicit types", VersionTag{ Version::ImplicitTypes }, VersionTag{ m_states->currentModule->metadata->shaderLangVersion }};
661+
654662
return ImplicitArrayType{};
663+
}
655664

656665
assert(std::holds_alternative<ExpressionType>(parameters[0]));
657666
const ExpressionType& exprType = std::get<ExpressionType>(parameters[0]);
@@ -733,10 +742,15 @@ namespace nzsl::Ast
733742

734743
RegisterPartialType(std::move(name), PartialType{
735744
{}, { TypeParameterCategory::PrimitiveType },
736-
[=](const TypeParameter* parameters, [[maybe_unused]] std::size_t parameterCount, const SourceLocation& sourceLocation) -> ExpressionType
745+
[=](const TypeParameter* parameters, std::size_t parameterCount, const SourceLocation& sourceLocation) -> ExpressionType
737746
{
738747
if (parameterCount == 0)
748+
{
749+
if (m_states->currentModule->metadata->shaderLangVersion < Version::ImplicitTypes)
750+
throw CompilerUnsupportedFeatureError{ sourceLocation, "implicit types", VersionTag{ Version::ImplicitTypes }, VersionTag{ m_states->currentModule->metadata->shaderLangVersion } };
751+
739752
return ImplicitMatrixType{ columnCount, rowCount };
753+
}
740754

741755
assert(parameterCount == 1);
742756
assert(std::holds_alternative<ExpressionType>(*parameters));
@@ -761,10 +775,15 @@ namespace nzsl::Ast
761775
{
762776
RegisterPartialType(fmt::format("vec{}", componentCount), PartialType {
763777
{}, { TypeParameterCategory::PrimitiveType },
764-
[=](const TypeParameter* parameters, [[maybe_unused]] std::size_t parameterCount, const SourceLocation& /*sourceLocation*/) -> ExpressionType
778+
[=](const TypeParameter* parameters, std::size_t parameterCount, const SourceLocation& sourceLocation) -> ExpressionType
765779
{
766780
if (parameterCount == 0)
781+
{
782+
if (m_states->currentModule->metadata->shaderLangVersion < Version::ImplicitTypes)
783+
throw CompilerUnsupportedFeatureError{ sourceLocation, "implicit types", VersionTag{ Version::ImplicitTypes }, VersionTag{ m_states->currentModule->metadata->shaderLangVersion } };
784+
767785
return ImplicitVectorType{ componentCount };
786+
}
768787

769788
assert(parameterCount == 1);
770789
assert(std::holds_alternative<ExpressionType>(*parameters));
@@ -1400,6 +1419,9 @@ namespace nzsl::Ast
14001419
std::size_t typeIndex = std::get<Type>(exprType).typeIndex;
14011420

14021421
const auto& typeData = m_context->types.Retrieve(typeIndex, sourceLocation);
1422+
if (typeData.check)
1423+
typeData.check(sourceLocation);
1424+
14031425
if (!std::holds_alternative<ExpressionType>(typeData.content))
14041426
throw CompilerFullTypeExpectedError{ sourceLocation, ToString(typeData, sourceLocation) };
14051427

@@ -1425,12 +1447,12 @@ namespace nzsl::Ast
14251447
if (!exprType)
14261448
return std::nullopt;
14271449

1428-
Transform(*expression->cachedExpressionType, sourceLocation);
1450+
Transform(*expression->cachedExpressionType, expression->sourceLocation);
14291451

14301452
//if (!IsTypeType(exprType))
14311453
// throw AstError{ "type expected" };
14321454

1433-
return ResolveType(*exprType, resolveAlias, sourceLocation);
1455+
return ResolveType(*exprType, resolveAlias, expression->sourceLocation);
14341456
}
14351457

14361458
auto ResolveTransformer::Transform(AccessIdentifierExpression&& accessIdentifier) -> ExpressionTransformation
@@ -1728,6 +1750,9 @@ namespace nzsl::Ast
17281750
indexedExpr = ShaderBuilder::TypeConstant(std::move(indexedType), TypeConstant::NaN);
17291751
else
17301752
throw CompilerUnexpectedAccessedTypeError{ accessIdentifier.sourceLocation };
1753+
1754+
if (m_states->currentModule->metadata->shaderLangVersion < Version::TypeConstants)
1755+
throw CompilerUnsupportedFeatureError{ accessIdentifier.sourceLocation, "type constant", VersionTag{ Version::TypeConstants }, VersionTag{ m_states->currentModule->metadata->shaderLangVersion } };
17311756
}
17321757
else
17331758
throw CompilerUnexpectedAccessedTypeError{ accessIdentifier.sourceLocation };
@@ -1817,6 +1842,9 @@ namespace nzsl::Ast
18171842
std::size_t typeIndex = std::get<Type>(resolvedExprType).typeIndex;
18181843
const auto& typeData = m_context->types.Retrieve(typeIndex, accessIndexExpr.sourceLocation);
18191844

1845+
if (typeData.check)
1846+
typeData.check(accessIndexExpr.sourceLocation);
1847+
18201848
if (!std::holds_alternative<PartialType>(typeData.content))
18211849
throw CompilerExpectedPartialTypeError{ accessIndexExpr.sourceLocation, ToString(typeData, accessIndexExpr.sourceLocation) };
18221850

@@ -2176,6 +2204,9 @@ namespace nzsl::Ast
21762204
std::size_t typeIndex = std::get<Type>(resolvedType).typeIndex;
21772205
const auto& type = m_context->types.Retrieve(typeIndex, callFuncExpr.sourceLocation);
21782206

2207+
if (type.check)
2208+
type.check(callFuncExpr.sourceLocation);
2209+
21792210
return std::visit(Nz::Overloaded{
21802211
[&](const ExpressionType& expressionType) -> ExpressionTransformation
21812212
{

src/NZSL/Lang/Errors.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <NZSL/Lang/Errors.hpp>
66
#include <NZSL/Parser.hpp>
77
#include <NZSL/Lang/LangData.hpp>
8+
#include <NZSL/Lang/Version.hpp>
89
#include <fmt/format.h>
910
#include <string>
1011
#include <utility>
@@ -94,6 +95,16 @@ struct fmt::formatter<nzsl::TokenType> : formatter<string_view>
9495
}
9596
};
9697

98+
template<>
99+
struct fmt::formatter<nzsl::VersionTag> : formatter<string_view>
100+
{
101+
template<typename FormatContext>
102+
auto format(const nzsl::VersionTag& p, FormatContext& ctx) const -> decltype(ctx.out())
103+
{
104+
return formatter<string_view>::format(nzsl::Version::ToString(p.version), ctx);
105+
}
106+
};
107+
97108
namespace nzsl
98109
{
99110
std::string_view ToString(ErrorCategory errorCategory)

tests/src/Tests/ErrorsTests.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ fn main()
731731
{
732732
let x: f64 = 0.0;
733733
}
734-
)"), "(7,9 -> 11): CUnknownIdentifier error: unknown identifier f64");
734+
)"), "(7,9 -> 11): CModuleFeatureNotEnabled error: using f64 requires module feature float64 to be enabled");
735735

736736
// Primitive externals
737737
CHECK_THROWS_WITH(Compile(R"(
@@ -745,6 +745,30 @@ external
745745
)"), "(7,15 -> 29): CExtTypeNotAllowed error: external variable data has unauthorized type (mat4[f32]): only storage buffers, samplers, push constants and uniform buffers (and primitives, vectors and matrices if primitive external feature is enabled) are allowed in external blocks");
746746
}
747747

748+
// NZSL 1.1 features
749+
750+
// Implicit types
751+
CHECK_THROWS_WITH(Compile(R"(
752+
[nzsl_version("1.0")]
753+
module;
754+
755+
fn main()
756+
{
757+
let v = vec3(1, 2, 3);
758+
}
759+
)"), "(7,10 -> 22): CUnsupportedFeature error: \"implicit types\" feature requires NZSL 1.1 (current module version is 1.0)");
760+
761+
// Type constants
762+
CHECK_THROWS_WITH(Compile(R"(
763+
[nzsl_version("1.0")]
764+
module;
765+
766+
fn main()
767+
{
768+
let x = u32.Max;
769+
}
770+
)"), "(7,10 -> 16): CUnsupportedFeature error: \"type constant\" feature requires NZSL 1.1 (current module version is 1.0)");
771+
748772
/************************************************************************/
749773

750774
SECTION("Functions")

0 commit comments

Comments
 (0)