mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-18 20:43:32 +00:00
This CL moves sem/type and copies sem/node into the type/ folder. The type subclasses are moved over to using type::Type while remaining in the sem:: namespace. They will be moved over in followup CLs. Bug: tint:1718 Change-Id: I3f3495328d734f88e4fc2dfbc6705343f1198dc5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113180 Reviewed-by: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
539 lines
22 KiB
C++
539 lines
22 KiB
C++
// Copyright 2020 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_VALIDATOR_H_
|
|
#define SRC_TINT_RESOLVER_VALIDATOR_H_
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "src/tint/ast/pipeline_stage.h"
|
|
#include "src/tint/program_builder.h"
|
|
#include "src/tint/resolver/sem_helper.h"
|
|
#include "src/tint/sem/evaluation_stage.h"
|
|
#include "src/tint/source.h"
|
|
#include "src/tint/utils/hash.h"
|
|
#include "src/tint/utils/hashmap.h"
|
|
#include "src/tint/utils/vector.h"
|
|
|
|
// Forward declarations
|
|
namespace tint::ast {
|
|
class IndexAccessorExpression;
|
|
class BinaryExpression;
|
|
class BitcastExpression;
|
|
class CallExpression;
|
|
class CallStatement;
|
|
class CaseStatement;
|
|
class ForLoopStatement;
|
|
class Function;
|
|
class IdentifierExpression;
|
|
class LoopStatement;
|
|
class MemberAccessorExpression;
|
|
class ReturnStatement;
|
|
class SwitchStatement;
|
|
class UnaryOpExpression;
|
|
class Variable;
|
|
class WhileStatement;
|
|
} // namespace tint::ast
|
|
namespace tint::sem {
|
|
class Array;
|
|
class Atomic;
|
|
class BlockStatement;
|
|
class BreakIfStatement;
|
|
class Builtin;
|
|
class Call;
|
|
class CaseStatement;
|
|
class ForLoopStatement;
|
|
class IfStatement;
|
|
class LoopStatement;
|
|
class Materialize;
|
|
class Statement;
|
|
class SwitchStatement;
|
|
class TypeInitializer;
|
|
class WhileStatement;
|
|
} // namespace tint::sem
|
|
|
|
namespace tint::resolver {
|
|
|
|
/// TypeAndAddressSpace is a pair of type and address space
|
|
struct TypeAndAddressSpace {
|
|
/// The type
|
|
const type::Type* type;
|
|
/// The address space
|
|
ast::AddressSpace address_space;
|
|
|
|
/// Equality operator
|
|
/// @param other the other TypeAndAddressSpace to compare this TypeAndAddressSpace to
|
|
/// @returns true if the type and address space of this TypeAndAddressSpace is equal to @p other
|
|
bool operator==(const TypeAndAddressSpace& other) const {
|
|
return type == other.type && address_space == other.address_space;
|
|
}
|
|
};
|
|
|
|
/// Validation logic for various ast nodes. The validations in general should
|
|
/// be shallow and depend on the resolver to call on children. The validations
|
|
/// also assume that sem changes have already been made. The validation checks
|
|
/// should not alter the AST or SEM trees.
|
|
class Validator {
|
|
public:
|
|
/// Constructor
|
|
/// @param builder the program builder
|
|
/// @param helper the SEM helper to validate with
|
|
/// @param enabled_extensions all the extensions declared in current module
|
|
/// @param atomic_composite_info atomic composite info of the module
|
|
/// @param valid_type_storage_layouts a set of validated type layouts by address space
|
|
Validator(ProgramBuilder* builder,
|
|
SemHelper& helper,
|
|
const ast::Extensions& enabled_extensions,
|
|
const utils::Hashmap<const type::Type*, const Source*, 8>& atomic_composite_info,
|
|
utils::Hashset<TypeAndAddressSpace, 8>& valid_type_storage_layouts);
|
|
~Validator();
|
|
|
|
/// Adds the given error message to the diagnostics
|
|
/// @param msg the error message
|
|
/// @param source the error source
|
|
void AddError(const std::string& msg, const Source& source) const;
|
|
|
|
/// Adds the given warning message to the diagnostics
|
|
/// @param msg the warning message
|
|
/// @param source the warning source
|
|
void AddWarning(const std::string& msg, const Source& source) const;
|
|
|
|
/// Adds the given note message to the diagnostics
|
|
/// @param msg the note message
|
|
/// @param source the note source
|
|
void AddNote(const std::string& msg, const Source& source) const;
|
|
|
|
/// @param type the given type
|
|
/// @returns true if the given type is a plain type
|
|
bool IsPlain(const type::Type* type) const;
|
|
|
|
/// @param type the given type
|
|
/// @returns true if the given type is a fixed-footprint type
|
|
bool IsFixedFootprint(const type::Type* type) const;
|
|
|
|
/// @param type the given type
|
|
/// @returns true if the given type is storable
|
|
bool IsStorable(const type::Type* type) const;
|
|
|
|
/// @param type the given type
|
|
/// @returns true if the given type is host-shareable
|
|
bool IsHostShareable(const type::Type* type) const;
|
|
|
|
/// Validates pipeline stages
|
|
/// @param entry_points the entry points to the module
|
|
/// @returns true on success, false otherwise.
|
|
bool PipelineStages(utils::VectorRef<sem::Function*> entry_points) const;
|
|
|
|
/// Validates push_constant variables
|
|
/// @param entry_points the entry points to the module
|
|
/// @returns true on success, false otherwise.
|
|
bool PushConstants(utils::VectorRef<sem::Function*> entry_points) const;
|
|
|
|
/// Validates aliases
|
|
/// @param alias the alias to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool Alias(const ast::Alias* alias) const;
|
|
|
|
/// Validates the array
|
|
/// @param arr the array to validate
|
|
/// @param el_source the source of the array element, or the array if the array does not have a
|
|
/// locally-declared element AST node.
|
|
/// @returns true on success, false otherwise.
|
|
bool Array(const sem::Array* arr, const Source& el_source) const;
|
|
|
|
/// Validates an array stride attribute
|
|
/// @param attr the stride attribute to validate
|
|
/// @param el_size the element size
|
|
/// @param el_align the element alignment
|
|
/// @returns true on success, false otherwise
|
|
bool ArrayStrideAttribute(const ast::StrideAttribute* attr,
|
|
uint32_t el_size,
|
|
uint32_t el_align) const;
|
|
|
|
/// Validates an atomic type
|
|
/// @param a the atomic ast node
|
|
/// @param s the atomic sem node
|
|
/// @returns true on success, false otherwise.
|
|
bool Atomic(const ast::Atomic* a, const sem::Atomic* s) const;
|
|
|
|
/// Validates a pointer type
|
|
/// @param a the pointer ast node
|
|
/// @param s the pointer sem node
|
|
/// @returns true on success, false otherwise.
|
|
bool Pointer(const ast::Pointer* a, const sem::Pointer* s) const;
|
|
|
|
/// Validates an assignment
|
|
/// @param a the assignment statement
|
|
/// @param rhs_ty the type of the right hand side
|
|
/// @returns true on success, false otherwise.
|
|
bool Assignment(const ast::Statement* a, const type::Type* rhs_ty) const;
|
|
|
|
/// Validates a bitcase
|
|
/// @param cast the bitcast expression
|
|
/// @param to the destination type
|
|
/// @returns true on success, false otherwise
|
|
bool Bitcast(const ast::BitcastExpression* cast, const type::Type* to) const;
|
|
|
|
/// Validates a break statement
|
|
/// @param stmt the break statement to validate
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise.
|
|
bool BreakStatement(const sem::Statement* stmt, sem::Statement* current_statement) const;
|
|
|
|
/// Validates a builtin attribute
|
|
/// @param attr the attribute to validate
|
|
/// @param storage_type the attribute storage type
|
|
/// @param stage the current pipeline stage
|
|
/// @param is_input true if this is an input attribute
|
|
/// @returns true on success, false otherwise.
|
|
bool BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
|
const type::Type* storage_type,
|
|
ast::PipelineStage stage,
|
|
const bool is_input) const;
|
|
|
|
/// Validates a continue statement
|
|
/// @param stmt the continue statement to validate
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise
|
|
bool ContinueStatement(const sem::Statement* stmt, sem::Statement* current_statement) const;
|
|
|
|
/// Validates a call
|
|
/// @param call the call
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise
|
|
bool Call(const sem::Call* call, sem::Statement* current_statement) const;
|
|
|
|
/// Validates an entry point
|
|
/// @param func the entry point function to validate
|
|
/// @param stage the pipeline stage for the entry point
|
|
/// @returns true on success, false otherwise
|
|
bool EntryPoint(const sem::Function* func, ast::PipelineStage stage) const;
|
|
|
|
/// Validates that the expression must not be evaluated any later than @p latest_stage
|
|
/// @param expr the expression to check
|
|
/// @param latest_stage the latest evaluation stage that the expression can be evaluated
|
|
/// @param constraint the 'thing' that is imposing the contraint. e.g. "var declaration"
|
|
/// @returns true if @p expr is evaluated in or before @p latest_stage, false otherwise
|
|
bool EvaluationStage(const sem::Expression* expr,
|
|
sem::EvaluationStage latest_stage,
|
|
std::string_view constraint) const;
|
|
|
|
/// Validates a for loop
|
|
/// @param stmt the for loop statement to validate
|
|
/// @returns true on success, false otherwise
|
|
bool ForLoopStatement(const sem::ForLoopStatement* stmt) const;
|
|
|
|
/// Validates a while loop
|
|
/// @param stmt the while statement to validate
|
|
/// @returns true on success, false otherwise
|
|
bool WhileStatement(const sem::WhileStatement* stmt) const;
|
|
|
|
/// Validates a function
|
|
/// @param func the function to validate
|
|
/// @param stage the current pipeline stage
|
|
/// @returns true on success, false otherwise.
|
|
bool Function(const sem::Function* func, ast::PipelineStage stage) const;
|
|
|
|
/// Validates a function call
|
|
/// @param call the function call to validate
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise
|
|
bool FunctionCall(const sem::Call* call, sem::Statement* current_statement) const;
|
|
|
|
/// Validates a global variable
|
|
/// @param var the global variable to validate
|
|
/// @param override_id the set of override ids in the module
|
|
/// @returns true on success, false otherwise
|
|
bool GlobalVariable(
|
|
const sem::GlobalVariable* var,
|
|
const utils::Hashmap<OverrideId, const sem::Variable*, 8>& override_id) const;
|
|
|
|
/// Validates a break-if statement
|
|
/// @param stmt the statement to validate
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise
|
|
bool BreakIfStatement(const sem::BreakIfStatement* stmt,
|
|
sem::Statement* current_statement) const;
|
|
|
|
/// Validates an if statement
|
|
/// @param stmt the statement to validate
|
|
/// @returns true on success, false otherwise
|
|
bool IfStatement(const sem::IfStatement* stmt) const;
|
|
|
|
/// Validates an increment or decrement statement
|
|
/// @param stmt the statement to validate
|
|
/// @returns true on success, false otherwise
|
|
bool IncrementDecrementStatement(const ast::IncrementDecrementStatement* stmt) const;
|
|
|
|
/// Validates an interpolate attribute
|
|
/// @param attr the interpolation attribute to validate
|
|
/// @param storage_type the storage type of the attached variable
|
|
/// @returns true on succes, false otherwise
|
|
bool InterpolateAttribute(const ast::InterpolateAttribute* attr,
|
|
const type::Type* storage_type) const;
|
|
|
|
/// Validates a builtin call
|
|
/// @param call the builtin call to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool BuiltinCall(const sem::Call* call) const;
|
|
|
|
/// Validates a local variable
|
|
/// @param v the variable to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool LocalVariable(const sem::Variable* v) const;
|
|
|
|
/// Validates a location attribute
|
|
/// @param loc_attr the location attribute to validate
|
|
/// @param location the location value
|
|
/// @param type the variable type
|
|
/// @param locations the set of locations in the module
|
|
/// @param stage the current pipeline stage
|
|
/// @param source the source of the attribute
|
|
/// @param is_input true if this is an input variable
|
|
/// @returns true on success, false otherwise.
|
|
bool LocationAttribute(const ast::LocationAttribute* loc_attr,
|
|
uint32_t location,
|
|
const type::Type* type,
|
|
utils::Hashset<uint32_t, 8>& locations,
|
|
ast::PipelineStage stage,
|
|
const Source& source,
|
|
const bool is_input = false) const;
|
|
|
|
/// Validates a loop statement
|
|
/// @param stmt the loop statement
|
|
/// @returns true on success, false otherwise.
|
|
bool LoopStatement(const sem::LoopStatement* stmt) const;
|
|
|
|
/// Validates a materialize of an abstract numeric value from the type `from` to the type `to`.
|
|
/// @param to the target type
|
|
/// @param from the abstract numeric type
|
|
/// @param source the source of the materialization
|
|
/// @returns true on success, false otherwise
|
|
bool Materialize(const type::Type* to, const type::Type* from, const Source& source) const;
|
|
|
|
/// Validates a matrix
|
|
/// @param ty the matrix to validate
|
|
/// @param source the source of the matrix
|
|
/// @returns true on success, false otherwise
|
|
bool Matrix(const sem::Matrix* ty, const Source& source) const;
|
|
|
|
/// Validates a function parameter
|
|
/// @param func the function the variable is for
|
|
/// @param var the variable to validate
|
|
/// @returns true on success, false otherwise
|
|
bool Parameter(const ast::Function* func, const sem::Variable* var) const;
|
|
|
|
/// Validates a return
|
|
/// @param ret the return statement to validate
|
|
/// @param func_type the return type of the curreunt function
|
|
/// @param ret_type the return type
|
|
/// @param current_statement the current statement being resolved
|
|
/// @returns true on success, false otherwise
|
|
bool Return(const ast::ReturnStatement* ret,
|
|
const type::Type* func_type,
|
|
const type::Type* ret_type,
|
|
sem::Statement* current_statement) const;
|
|
|
|
/// Validates a list of statements
|
|
/// @param stmts the statements to validate
|
|
/// @returns true on success, false otherwise
|
|
bool Statements(utils::VectorRef<const ast::Statement*> stmts) const;
|
|
|
|
/// Validates a storage texture
|
|
/// @param t the texture to validate
|
|
/// @returns true on success, false otherwise
|
|
bool StorageTexture(const ast::StorageTexture* t) const;
|
|
|
|
/// Validates a sampled texture
|
|
/// @param t the texture to validate
|
|
/// @param source the source of the texture
|
|
/// @returns true on success, false otherwise
|
|
bool SampledTexture(const sem::SampledTexture* t, const Source& source) const;
|
|
|
|
/// Validates a multisampled texture
|
|
/// @param t the texture to validate
|
|
/// @param source the source of the texture
|
|
/// @returns true on success, false otherwise
|
|
bool MultisampledTexture(const sem::MultisampledTexture* t, const Source& source) const;
|
|
|
|
/// Validates a structure
|
|
/// @param str the structure to validate
|
|
/// @param stage the current pipeline stage
|
|
/// @returns true on success, false otherwise.
|
|
bool Structure(const sem::Struct* str, ast::PipelineStage stage) const;
|
|
|
|
/// Validates a structure initializer
|
|
/// @param ctor the call expression to validate
|
|
/// @param struct_type the type of the structure
|
|
/// @returns true on success, false otherwise
|
|
bool StructureInitializer(const ast::CallExpression* ctor,
|
|
const sem::Struct* struct_type) const;
|
|
|
|
/// Validates a switch statement
|
|
/// @param s the switch to validate
|
|
/// @returns true on success, false otherwise
|
|
bool SwitchStatement(const ast::SwitchStatement* s);
|
|
|
|
/// Validates a 'var' variable declaration
|
|
/// @param v the variable to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool Var(const sem::Variable* v) const;
|
|
|
|
/// Validates a 'let' variable declaration
|
|
/// @param v the variable to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool Let(const sem::Variable* v) const;
|
|
|
|
/// Validates a 'override' variable declaration
|
|
/// @param v the variable to validate
|
|
/// @param override_id the set of override ids in the module
|
|
/// @returns true on success, false otherwise.
|
|
bool Override(const sem::GlobalVariable* v,
|
|
const utils::Hashmap<OverrideId, const sem::Variable*, 8>& override_id) const;
|
|
|
|
/// Validates a 'const' variable declaration
|
|
/// @param v the variable to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool Const(const sem::Variable* v) const;
|
|
|
|
/// Validates a variable initializer
|
|
/// @param v the variable to validate
|
|
/// @param address_space the address space of the variable
|
|
/// @param storage_type the type of the storage
|
|
/// @param initializer the RHS initializer expression
|
|
/// @returns true on succes, false otherwise
|
|
bool VariableInitializer(const ast::Variable* v,
|
|
ast::AddressSpace address_space,
|
|
const type::Type* storage_type,
|
|
const sem::Expression* initializer) const;
|
|
|
|
/// Validates a vector
|
|
/// @param ty the vector to validate
|
|
/// @param source the source of the vector
|
|
/// @returns true on success, false otherwise
|
|
bool Vector(const sem::Vector* ty, const Source& source) const;
|
|
|
|
/// Validates an array initializer
|
|
/// @param ctor the call expresion to validate
|
|
/// @param arr_type the type of the array
|
|
/// @returns true on success, false otherwise
|
|
bool ArrayInitializer(const ast::CallExpression* ctor, const sem::Array* arr_type) const;
|
|
|
|
/// Validates a texture builtin function
|
|
/// @param call the builtin call to validate
|
|
/// @returns true on success, false otherwise
|
|
bool TextureBuiltinFunction(const sem::Call* call) const;
|
|
|
|
/// Validates an optional builtin function and its required extension.
|
|
/// @param call the builtin call to validate
|
|
/// @returns true on success, false otherwise
|
|
bool RequiredExtensionForBuiltinFunction(const sem::Call* call) const;
|
|
|
|
/// Validates there are no duplicate attributes
|
|
/// @param attributes the list of attributes to validate
|
|
/// @returns true on success, false otherwise.
|
|
bool NoDuplicateAttributes(utils::VectorRef<const ast::Attribute*> attributes) const;
|
|
|
|
/// Validates a address space layout
|
|
/// @param type the type to validate
|
|
/// @param sc the address space
|
|
/// @param source the source of the type
|
|
/// @returns true on success, false otherwise
|
|
bool AddressSpaceLayout(const type::Type* type, ast::AddressSpace sc, Source source) const;
|
|
|
|
/// @returns true if the attribute list contains a
|
|
/// ast::DisableValidationAttribute with the validation mode equal to
|
|
/// `validation`
|
|
/// @param attributes the attribute list to check
|
|
/// @param validation the validation mode to check
|
|
bool IsValidationDisabled(utils::VectorRef<const ast::Attribute*> attributes,
|
|
ast::DisabledValidation validation) const;
|
|
|
|
/// @returns true if the attribute list does not contains a
|
|
/// ast::DisableValidationAttribute with the validation mode equal to
|
|
/// `validation`
|
|
/// @param attributes the attribute list to check
|
|
/// @param validation the validation mode to check
|
|
bool IsValidationEnabled(utils::VectorRef<const ast::Attribute*> attributes,
|
|
ast::DisabledValidation validation) const;
|
|
|
|
private:
|
|
/// @param ty the type to check
|
|
/// @returns true if @p ty is an array with an `override` expression element count, otherwise
|
|
/// false.
|
|
bool IsArrayWithOverrideCount(const type::Type* ty) const;
|
|
|
|
/// Raises an error about an array type using an `override` expression element count, outside
|
|
/// the single allowed use of a `var<workgroup>`.
|
|
/// @param source the source for the error
|
|
void RaiseArrayWithOverrideCountError(const Source& source) const;
|
|
|
|
/// Searches the current statement and up through parents of the current
|
|
/// statement looking for a loop or for-loop continuing statement.
|
|
/// @returns the closest continuing statement to the current statement that
|
|
/// (transitively) owns the current statement.
|
|
/// @param stop_at_loop if true then the function will return nullptr if a
|
|
/// loop or for-loop was found before the continuing.
|
|
/// @param current_statement the current statement being resolved
|
|
const ast::Statement* ClosestContinuing(bool stop_at_loop,
|
|
sem::Statement* current_statement) const;
|
|
|
|
/// Returns a human-readable string representation of the vector type name
|
|
/// with the given parameters.
|
|
/// @param size the vector dimension
|
|
/// @param element_type scalar vector sub-element type
|
|
/// @return pretty string representation
|
|
std::string VectorPretty(uint32_t size, const type::Type* element_type) const;
|
|
|
|
/// Raises an error if combination of @p store_ty, @p access and @p address_space are not valid
|
|
/// for a `var` or `ptr` declaration.
|
|
/// @param store_ty the store type of the var or pointer
|
|
/// @param access the var or pointer access
|
|
/// @param address_space the var or pointer address space
|
|
/// @param source the source for the error
|
|
/// @returns true on success, false if an error was raised.
|
|
bool CheckTypeAccessAddressSpace(const type::Type* store_ty,
|
|
ast::Access access,
|
|
ast::AddressSpace address_space,
|
|
utils::VectorRef<const tint::ast::Attribute*> attributes,
|
|
const Source& source) const;
|
|
SymbolTable& symbols_;
|
|
diag::List& diagnostics_;
|
|
SemHelper& sem_;
|
|
const ast::Extensions& enabled_extensions_;
|
|
const utils::Hashmap<const type::Type*, const Source*, 8>& atomic_composite_info_;
|
|
utils::Hashset<TypeAndAddressSpace, 8>& valid_type_storage_layouts_;
|
|
};
|
|
|
|
} // namespace tint::resolver
|
|
|
|
namespace std {
|
|
|
|
/// Custom std::hash specialization for tint::resolver::TypeAndAddressSpace.
|
|
template <>
|
|
class hash<tint::resolver::TypeAndAddressSpace> {
|
|
public:
|
|
/// @param tas the TypeAndAddressSpace
|
|
/// @return the hash value
|
|
inline std::size_t operator()(const tint::resolver::TypeAndAddressSpace& tas) const {
|
|
return tint::utils::Hash(tas.type, tas.address_space);
|
|
}
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
#endif // SRC_TINT_RESOLVER_VALIDATOR_H_
|