// Copyright 2021 The Tint Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef SRC_TINT_RESOLVER_DEPENDENCY_GRAPH_H_ #define SRC_TINT_RESOLVER_DEPENDENCY_GRAPH_H_ #include #include #include "src/tint/ast/module.h" #include "src/tint/builtin/access.h" #include "src/tint/builtin/builtin.h" #include "src/tint/builtin/builtin_value.h" #include "src/tint/builtin/function.h" #include "src/tint/builtin/interpolation_sampling.h" #include "src/tint/builtin/interpolation_type.h" #include "src/tint/builtin/texel_format.h" #include "src/tint/diagnostic/diagnostic.h" #include "src/tint/symbol_table.h" #include "src/tint/utils/hashmap.h" namespace tint::resolver { /// UnresolvedIdentifier is the variant value used by ResolvedIdentifier struct UnresolvedIdentifier { /// Name of the unresolved identifier std::string name; }; /// ResolvedIdentifier holds the resolution of an ast::Identifier. /// Can hold one of: /// - UnresolvedIdentifier /// - const ast::TypeDecl* (as const ast::Node*) /// - const ast::Variable* (as const ast::Node*) /// - const ast::Function* (as const ast::Node*) /// - builtin::Function /// - builtin::Access /// - builtin::AddressSpace /// - builtin::Builtin /// - builtin::BuiltinValue /// - builtin::InterpolationSampling /// - builtin::InterpolationType /// - builtin::TexelFormat class ResolvedIdentifier { public: /// Constructor /// @param value the resolved identifier value template ResolvedIdentifier(T value) : value_(value) {} // NOLINT(runtime/explicit) /// @return the UnresolvedIdentifier if the identifier was not resolved const UnresolvedIdentifier* Unresolved() const { if (auto n = std::get_if(&value_)) { return n; } return nullptr; } /// @return the node pointer if the ResolvedIdentifier holds an AST node, otherwise nullptr const ast::Node* Node() const { if (auto n = std::get_if(&value_)) { return *n; } return nullptr; } /// @return the builtin function if the ResolvedIdentifier holds builtin::Function, otherwise /// builtin::Function::kNone builtin::Function BuiltinFunction() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::Function::kNone; } /// @return the access if the ResolvedIdentifier holds builtin::Access, otherwise /// builtin::Access::kUndefined builtin::Access Access() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::Access::kUndefined; } /// @return the address space if the ResolvedIdentifier holds builtin::AddressSpace, otherwise /// builtin::AddressSpace::kUndefined builtin::AddressSpace AddressSpace() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::AddressSpace::kUndefined; } /// @return the builtin type if the ResolvedIdentifier holds builtin::Builtin, otherwise /// builtin::Builtin::kUndefined builtin::Builtin BuiltinType() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::Builtin::kUndefined; } /// @return the builtin value if the ResolvedIdentifier holds builtin::BuiltinValue, otherwise /// builtin::BuiltinValue::kUndefined builtin::BuiltinValue BuiltinValue() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::BuiltinValue::kUndefined; } /// @return the texel format if the ResolvedIdentifier holds type::InterpolationSampling, /// otherwise type::InterpolationSampling::kUndefined builtin::InterpolationSampling InterpolationSampling() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::InterpolationSampling::kUndefined; } /// @return the texel format if the ResolvedIdentifier holds type::InterpolationType, /// otherwise type::InterpolationType::kUndefined builtin::InterpolationType InterpolationType() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::InterpolationType::kUndefined; } /// @return the texel format if the ResolvedIdentifier holds type::TexelFormat, otherwise /// type::TexelFormat::kUndefined builtin::TexelFormat TexelFormat() const { if (auto n = std::get_if(&value_)) { return *n; } return builtin::TexelFormat::kUndefined; } /// @param value the value to compare the ResolvedIdentifier to /// @return true if the ResolvedIdentifier is equal to @p value template bool operator==(const T& value) const { if (auto n = std::get_if(&value_)) { return *n == value; } return false; } /// @param other the other value to compare to this /// @return true if this ResolvedIdentifier and @p other are not equal template bool operator!=(const T& other) const { return !(*this == other); } /// @param symbols the program's symbol table /// @param diagnostics diagnostics used to report ICEs /// @return a description of the resolved symbol std::string String(const SymbolTable& symbols, diag::List& diagnostics) const; private: std::variant value_; }; /// DependencyGraph holds information about module-scope declaration dependency /// analysis and symbol resolutions. struct DependencyGraph { /// Constructor DependencyGraph(); /// Move-constructor DependencyGraph(DependencyGraph&&); /// Destructor ~DependencyGraph(); /// Build() performs symbol resolution and dependency analysis on `module`, /// populating `output` with the resulting dependency graph. /// @param module the AST module to analyse /// @param symbols the symbol table /// @param diagnostics the diagnostic list to populate with errors / warnings /// @param output the resulting DependencyGraph /// @returns true on success, false on error static bool Build(const ast::Module& module, const SymbolTable& symbols, diag::List& diagnostics, DependencyGraph& output); /// All globals in dependency-sorted order. utils::Vector ordered_globals; /// Map of ast::Identifier to a ResolvedIdentifier utils::Hashmap resolved_identifiers; /// Map of ast::Variable to a type, function, or variable that is shadowed by /// the variable key. A declaration (X) shadows another (Y) if X and Y use /// the same symbol, and X is declared in a sub-scope of the scope that /// declares Y. utils::Hashmap shadows; }; } // namespace tint::resolver #endif // SRC_TINT_RESOLVER_DEPENDENCY_GRAPH_H_