// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Shader module" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once #ifndef NAZARA_SHADER_AST_SANITIZEVISITOR_HPP #define NAZARA_SHADER_AST_SANITIZEVISITOR_HPP #include #include #include #include #include #include #include #include #include #include #include namespace Nz::ShaderAst { class NAZARA_SHADER_API SanitizeVisitor final : AstCloner { friend class AstTypeExpressionVisitor; public: struct Options; SanitizeVisitor() = default; SanitizeVisitor(const SanitizeVisitor&) = delete; SanitizeVisitor(SanitizeVisitor&&) = delete; ~SanitizeVisitor() = default; inline ModulePtr Sanitize(const Module& module, std::string* error = nullptr); ModulePtr Sanitize(const Module& module, const Options& options, std::string* error = nullptr); SanitizeVisitor& operator=(const SanitizeVisitor&) = delete; SanitizeVisitor& operator=(SanitizeVisitor&&) = delete; static UInt32 ToSwizzleIndex(char c); struct Options { std::shared_ptr moduleResolver; std::unordered_set reservedIdentifiers; std::unordered_map optionValues; bool makeVariableNameUnique = false; bool reduceLoopsToWhile = false; bool removeAliases = false; bool removeConstDeclaration = false; bool removeCompoundAssignments = false; bool removeMatrixCast = false; bool removeOptionDeclaration = false; bool removeScalarSwizzling = false; bool splitMultipleBranches = false; bool useIdentifierAccessesForStructs = true; }; private: enum class IdentifierCategory; struct CurrentFunctionData; struct Environment; struct FunctionData; struct Identifier; struct IdentifierData; template struct IdentifierList; struct Scope; using AstCloner::CloneExpression; ExpressionValue CloneType(const ExpressionValue& exprType) override; ExpressionPtr Clone(AccessIdentifierExpression& node) override; ExpressionPtr Clone(AccessIndexExpression& node) override; ExpressionPtr Clone(AliasValueExpression& node) override; ExpressionPtr Clone(AssignExpression& node) override; ExpressionPtr Clone(BinaryExpression& node) override; ExpressionPtr Clone(CallFunctionExpression& node) override; ExpressionPtr Clone(CastExpression& node) override; ExpressionPtr Clone(ConditionalExpression& node) override; ExpressionPtr Clone(ConstantValueExpression& node) override; ExpressionPtr Clone(ConstantExpression& node) override; ExpressionPtr Clone(IdentifierExpression& node) override; ExpressionPtr Clone(IntrinsicExpression& node) override; ExpressionPtr Clone(SwizzleExpression& node) override; ExpressionPtr Clone(UnaryExpression& node) override; ExpressionPtr Clone(VariableValueExpression& node) override; StatementPtr Clone(BranchStatement& node) override; StatementPtr Clone(ConditionalStatement& node) override; StatementPtr Clone(DeclareAliasStatement& node) override; StatementPtr Clone(DeclareConstStatement& node) override; StatementPtr Clone(DeclareExternalStatement& node) override; StatementPtr Clone(DeclareFunctionStatement& node) override; StatementPtr Clone(DeclareOptionStatement& node) override; StatementPtr Clone(DeclareStructStatement& node) override; StatementPtr Clone(DeclareVariableStatement& node) override; StatementPtr Clone(DiscardStatement& node) override; StatementPtr Clone(ExpressionStatement& node) override; StatementPtr Clone(ForStatement& node) override; StatementPtr Clone(ForEachStatement& node) override; StatementPtr Clone(ImportStatement& node) override; StatementPtr Clone(MultiStatement& node) override; StatementPtr Clone(ScopedStatement& node) override; StatementPtr Clone(WhileStatement& node) override; const IdentifierData* FindIdentifier(const std::string_view& identifierName) const; template const IdentifierData* FindIdentifier(const std::string_view& identifierName, F&& functor) const; const IdentifierData* FindIdentifier(const Environment& environment, const std::string_view& identifierName) const; template const IdentifierData* FindIdentifier(const Environment& environment, const std::string_view& identifierName, F&& functor) const; TypeParameter FindTypeParameter(const std::string_view& identifierName) const; ExpressionPtr HandleIdentifier(const IdentifierData* identifierData); Expression& MandatoryExpr(const ExpressionPtr& node) const; Statement& MandatoryStatement(const StatementPtr& node) const; void PushScope(); void PopScope(); ExpressionPtr CacheResult(ExpressionPtr expression); ConstantValue ComputeConstantValue(Expression& expr) const; template const T& ComputeExprValue(ExpressionValue& attribute) const; template std::unique_ptr PropagateConstants(T& node) const; void PreregisterIndices(const Module& module); void PropagateFunctionFlags(std::size_t funcIndex, FunctionFlags flags, Bitset<>& seen); void RegisterBuiltin(); std::size_t RegisterAlias(std::string name, IdentifierData aliasData, std::optional index = {}); std::size_t RegisterConstant(std::string name, ConstantValue value, std::optional index = {}); std::size_t RegisterFunction(std::string name, FunctionData funcData, std::optional index = {}); std::size_t RegisterIntrinsic(std::string name, IntrinsicType type); std::size_t RegisterModule(std::string moduleIdentifier, std::size_t moduleIndex); std::size_t RegisterStruct(std::string name, StructDescription* description, std::optional index = {}); std::size_t RegisterType(std::string name, ExpressionType expressionType, std::optional index = {}); std::size_t RegisterType(std::string name, PartialType partialType, std::optional index = {}); std::size_t RegisterVariable(std::string name, ExpressionType type, std::optional index = {}); const IdentifierData* ResolveAliasIdentifier(const IdentifierData* identifier) const; void ResolveFunctions(); const ExpressionPtr& ResolveCondExpression(ConditionalExpression& node); std::size_t ResolveStruct(const AliasType& aliasType); std::size_t ResolveStruct(const ExpressionType& exprType); std::size_t ResolveStruct(const IdentifierType& identifierType); std::size_t ResolveStruct(const StructType& structType); std::size_t ResolveStruct(const UniformType& uniformType); ExpressionType ResolveType(const ExpressionType& exprType, bool resolveAlias = false); ExpressionType ResolveType(const ExpressionValue& exprTypeValue, bool resolveAlias = false); void SanitizeIdentifier(std::string& identifier); MultiStatementPtr SanitizeInternal(MultiStatement& rootNode, std::string* error); void TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right) const; void TypeMustMatch(const ExpressionType& left, const ExpressionType& right) const; StatementPtr Unscope(StatementPtr node); void Validate(DeclareAliasStatement& node); void Validate(WhileStatement& node); void Validate(AccessIndexExpression& node); void Validate(AssignExpression& node); void Validate(BinaryExpression& node); void Validate(CallFunctionExpression& node); void Validate(CastExpression& node); void Validate(DeclareVariableStatement& node); void Validate(IntrinsicExpression& node); void Validate(SwizzleExpression& node); void Validate(UnaryExpression& node); void Validate(VariableValueExpression& node); ExpressionType ValidateBinaryOp(BinaryType op, const ExpressionPtr& leftExpr, const ExpressionPtr& rightExpr); enum class IdentifierCategory { Alias, Constant, Function, Intrinsic, Module, Struct, Type, Variable }; struct FunctionData { Bitset<> calledByFunctions; DeclareFunctionStatement* node; FunctionFlags flags; }; struct IdentifierData { std::size_t index; IdentifierCategory category; }; struct Identifier { std::string name; IdentifierData data; }; struct Context; Context* m_context; }; inline ModulePtr Sanitize(const Module& module, std::string* error = nullptr); inline ModulePtr Sanitize(const Module& module, const SanitizeVisitor::Options& options, std::string* error = nullptr); } #include #endif // NAZARA_SHADER_AST_SANITIZEVISITOR_HPP