dawn-cmake/src/ast/module.h

145 lines
4.7 KiB
C
Raw Normal View History

// Copyright 2021 The Tint Authors.
2020-03-02 20:47:43 +00:00
//
// 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_AST_MODULE_H_
#define SRC_AST_MODULE_H_
#include <string>
#include <vector>
#include "src/ast/function.h"
#include "src/ast/type.h"
2020-03-02 20:47:43 +00:00
namespace tint {
namespace ast {
class NamedType;
/// Module holds the top-level AST types, functions and global variables used by
/// a Program.
class Module : public Castable<Module, Node> {
public:
/// Constructor
/// @param program_id the identifier of the program that owns this node
/// @param source the source of the module
Module(ProgramID program_id, const Source& source);
/// Constructor
/// @param program_id the identifier of the program that owns this node
/// @param source the source of the module
/// @param global_decls the list of global types, functions, and variables, in
/// the order they were declared in the source program
Module(ProgramID program_id,
const Source& source,
std::vector<Cloneable*> global_decls);
/// Destructor
~Module() override;
/// @returns the ordered global declarations for the translation unit
const std::vector<Cloneable*>& GlobalDeclarations() const {
return global_declarations_;
}
/// Add a global variable to the Builder
/// @param var the variable to add
void AddGlobalVariable(ast::Variable* var) {
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TINT_ASSERT(var);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(var, program_id());
global_variables_.push_back(var);
global_declarations_.push_back(var);
}
/// @returns true if the module has the global declaration `decl`
/// @param decl the declaration to check
bool HasGlobalDeclaration(const Cloneable* decl) const {
for (auto* d : global_declarations_) {
if (d == decl) {
return true;
}
}
return false;
}
/// @returns the global variables for the translation unit
const VariableList& GlobalVariables() const { return global_variables_; }
/// @returns the global variables for the translation unit
VariableList& GlobalVariables() { return global_variables_; }
/// Adds a constructed type to the Builder.
/// The type must be an alias or a struct.
/// @param type the constructed type to add
void AddConstructedType(typ::Type type) {
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TINT_ASSERT(type);
constructed_types_.push_back(type);
global_declarations_.push_back(const_cast<sem::Type*>(type.sem));
}
/// @returns the NamedType registered as a ConstructedType()
/// @param name the name of the type to search for
const ast::NamedType* LookupType(Symbol name) const;
/// @returns the constructed types in the translation unit
const std::vector<typ::Type>& ConstructedTypes() const {
return constructed_types_;
}
/// Add a function to the Builder
/// @param func the function to add
void AddFunction(ast::Function* func) {
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TINT_ASSERT(func);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(func, program_id());
functions_.push_back(func);
global_declarations_.push_back(func);
}
/// @returns the functions declared in the translation unit
const FunctionList& Functions() const { return functions_; }
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
Module* Clone(CloneContext* ctx) const override;
/// Copy copies the content of the Module src into this module.
/// @param ctx the clone context
/// @param src the module to copy into this module
void Copy(CloneContext* ctx, const Module* src);
/// Writes a representation of the node to the output stream
/// @param sem the semantic info for the program
/// @param out the stream to write to
/// @param indent number of spaces to indent the node when writing
void to_str(const sem::Info& sem,
std::ostream& out,
size_t indent) const override;
/// @param sem the semantic info for the program
/// @returns a string representation of the Builder
std::string to_str(const sem::Info& sem) const;
private:
std::vector<Cloneable*> global_declarations_;
std::vector<typ::Type> constructed_types_;
FunctionList functions_;
VariableList global_variables_;
};
2020-03-02 20:47:43 +00:00
} // namespace ast
} // namespace tint
#endif // SRC_AST_MODULE_H_