dawn-cmake/src/tint/resolver/dependency_graph.h
Ben Clayton afc53fa942 tint/resolver: Bring back enum suggestions
The dependency graph no longer errors if a symbol cannot be resolved, instead the ResolvedIdentifier now has an unresolved variant.
This is required as the second resolve phase only has the full context of the identifier usage, to provide the hints.

Also: Split Slice out of the utils/vector.h, so it can be used as a lightweight view over static data.

Fixed: tint:1842
Change-Id: I31fa7697790be24c35b7e4fab5ca903c8a7afbba
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121020
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
2023-02-22 17:15:53 +00:00

224 lines
8.0 KiB
C++

// 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 <string>
#include <vector>
#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/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/sem/builtin_type.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*)
/// - sem::BuiltinType
/// - 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 <typename T>
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<UnresolvedIdentifier>(&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<const ast::Node*>(&value_)) {
return *n;
}
return nullptr;
}
/// @return the builtin function if the ResolvedIdentifier holds sem::BuiltinType, otherwise
/// sem::BuiltinType::kNone
sem::BuiltinType BuiltinFunction() const {
if (auto n = std::get_if<sem::BuiltinType>(&value_)) {
return *n;
}
return sem::BuiltinType::kNone;
}
/// @return the access if the ResolvedIdentifier holds builtin::Access, otherwise
/// builtin::Access::kUndefined
builtin::Access Access() const {
if (auto n = std::get_if<builtin::Access>(&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<builtin::AddressSpace>(&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<builtin::Builtin>(&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<builtin::BuiltinValue>(&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<builtin::InterpolationSampling>(&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<builtin::InterpolationType>(&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<builtin::TexelFormat>(&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 <typename T>
bool operator==(const T& value) const {
if (auto n = std::get_if<T>(&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 <typename T>
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<UnresolvedIdentifier,
const ast::Node*,
sem::BuiltinType,
builtin::Access,
builtin::AddressSpace,
builtin::Builtin,
builtin::BuiltinValue,
builtin::InterpolationSampling,
builtin::InterpolationType,
builtin::TexelFormat>
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<const ast::Node*, 32> ordered_globals;
/// Map of ast::Identifier to a ResolvedIdentifier
utils::Hashmap<const ast::Identifier*, ResolvedIdentifier, 64> 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<const ast::Variable*, const ast::Node*, 16> shadows;
};
} // namespace tint::resolver
#endif // SRC_TINT_RESOLVER_DEPENDENCY_GRAPH_H_