From a07396a13c10af50a2edded701c46edd713e972f Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Tue, 26 Jan 2021 16:57:10 +0000 Subject: [PATCH] Reintroduce ast::Module as the root AST structure Holds the global variables, constructed types and functions. Deprecate the functions on program that forward on to the module. These will be fixed up in another change. Bug: tint:390 Change-Id: I47b6921a7d84be18113dec830c8435d4e0d4182d Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38544 Reviewed-by: dan sinclair --- src/ast/module.cc | 98 ++++++++++++++++++++++++++++++++++- src/ast/module.h | 83 +++++++++++++++++++++++++++++- src/clone_context.cc | 9 ++++ src/clone_context.h | 9 ++++ src/program.cc | 84 +++++------------------------- src/program.h | 118 +++++++++++++++++++++++++++---------------- 6 files changed, 283 insertions(+), 118 deletions(-) diff --git a/src/ast/module.cc b/src/ast/module.cc index 0de64bbd81..e39e0487c2 100644 --- a/src/ast/module.cc +++ b/src/ast/module.cc @@ -1,4 +1,4 @@ -// Copyright 2020 The Tint Authors. +// 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. @@ -14,10 +14,104 @@ #include "src/ast/module.h" +#include +#include +#include + +#include "src/clone_context.h" +#include "src/program.h" +#include "src/type/alias_type.h" +#include "src/type/struct_type.h" + +TINT_INSTANTIATE_CLASS_ID(tint::ast::Module); + namespace tint { namespace ast { -// Placeholder +Module::Module() : Base(Source{}) {} + +Module::Module(std::vector constructed_types, + FunctionList functions, + VariableList global_variables) + : Base(Source{}), + constructed_types_(std::move(constructed_types)), + functions_(std::move(functions)), + global_variables_(std::move(global_variables)) {} + +Module::~Module() = default; + +bool Module::IsValid() const { + for (auto* var : global_variables_) { + if (var == nullptr || !var->IsValid()) { + return false; + } + } + for (auto* const ty : constructed_types_) { + if (ty == nullptr) { + return false; + } + if (auto* alias = ty->As()) { + if (alias->type() == nullptr) { + return false; + } + if (auto* str = alias->type()->As()) { + if (!str->symbol().IsValid()) { + return false; + } + } + } else if (auto* str = ty->As()) { + if (!str->symbol().IsValid()) { + return false; + } + } else { + return false; + } + } + for (auto* func : functions_) { + if (func == nullptr || !func->IsValid()) { + return false; + } + } + return true; +} + +Module* Module::Clone(CloneContext* ctx) const { + return ctx->dst->create(ctx->Clone(constructed_types_), + ctx->Clone(functions_), + ctx->Clone(global_variables_)); +} + +void Module::to_str(std::ostream& out, size_t indent) const { + make_indent(out, indent); + out << "Module{" << std::endl; + indent += 2; + for (auto* const ty : constructed_types_) { + make_indent(out, indent); + if (auto* alias = ty->As()) { + out << alias->symbol().to_str() << " -> " << alias->type()->type_name() + << std::endl; + if (auto* str = alias->type()->As()) { + str->impl()->to_str(out, indent); + } + } else if (auto* str = ty->As()) { + out << str->symbol().to_str() << " "; + str->impl()->to_str(out, indent); + } + } + for (auto* var : global_variables_) { + var->to_str(out, indent); + } + for (auto* func : functions_) { + func->to_str(out, indent); + } + out << "}" << std::endl; +} + +std::string Module::to_str() const { + std::ostringstream out; + to_str(out, 0); + return out.str(); +} } // namespace ast } // namespace tint diff --git a/src/ast/module.h b/src/ast/module.h index 3e2beebfd8..7227131fb6 100644 --- a/src/ast/module.h +++ b/src/ast/module.h @@ -1,4 +1,4 @@ -// Copyright 2020 The Tint Authors. +// 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. @@ -15,10 +15,89 @@ #ifndef SRC_AST_MODULE_H_ #define SRC_AST_MODULE_H_ +#include +#include + +#include "src/ast/function.h" +#include "src/ast/node.h" +#include "src/ast/variable.h" +#include "src/type/type.h" + namespace tint { namespace ast { -// Placeholder +/// Module holds the top-level AST types, functions and global variables used by +/// a Program. +class Module : public Castable { + public: + /// Constructor + Module(); + + /// Constructor + /// @param constructed_types the list of types explicitly declared in the AST + /// @param functions the list of program functions + /// @param global_variables the list of global variables + Module(std::vector constructed_types, + FunctionList functions, + VariableList global_variables); + + /// Destructor + ~Module() override; + + /// Add a global variable to the Builder + /// @param var the variable to add + void AddGlobalVariable(ast::Variable* var) { + global_variables_.push_back(var); + } + + /// @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(type::Type* type) { + constructed_types_.push_back(type); + } + + /// @returns the constructed types in the translation unit + const std::vector& ConstructedTypes() const { + return constructed_types_; + } + + /// @returns the functions declared in the translation unit + const FunctionList& Functions() const { return functions_; } + + /// @returns the functions declared in the translation unit + FunctionList& Functions() { return functions_; } + + /// @returns true if all required fields in the AST are present. + bool IsValid() const override; + + /// Clones this node and all transitive child nodes using the `CloneContext` + /// `ctx`. + /// @note Semantic information such as resolved expression type and intrinsic + /// information is not cloned. + /// @param ctx the clone context + /// @return the newly cloned node + Module* Clone(CloneContext* ctx) const override; + + /// Writes a representation of the node to the output stream + /// @param out the stream to write to + /// @param indent number of spaces to indent the node when writing + void to_str(std::ostream& out, size_t indent) const override; + + /// @returns a string representation of the Builder + std::string to_str() const; + + private: + std::vector constructed_types_; + FunctionList functions_; + VariableList global_variables_; +}; } // namespace ast } // namespace tint diff --git a/src/clone_context.cc b/src/clone_context.cc index 5eb1a86cf7..f9862443cc 100644 --- a/src/clone_context.cc +++ b/src/clone_context.cc @@ -30,4 +30,13 @@ void CloneContext::Clone() { src->Clone(this); } +ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) { + ast::FunctionList out; + out.reserve(v.size()); + for (ast::Function* el : v) { + out.Add(Clone(el)); + } + return out; +} + } // namespace tint diff --git a/src/clone_context.h b/src/clone_context.h index 1f742b931b..fc391b015b 100644 --- a/src/clone_context.h +++ b/src/clone_context.h @@ -19,6 +19,7 @@ #include #include +#include "src/ast/function.h" #include "src/castable.h" #include "src/source.h" #include "src/symbol.h" @@ -106,6 +107,14 @@ class CloneContext { return out; } + /// Clones each of the elements of the vector `v` into the Program #dst. + /// + /// All the elements of the vector `v` must be owned by the Program #src. + /// + /// @param v the vector to clone + /// @return the cloned vector + ast::FunctionList Clone(const ast::FunctionList& v); + /// ReplaceAll() registers `replacer` to be called whenever the Clone() method /// is called with a type that matches (or derives from) the type of the /// second parameter of `replacer`. diff --git a/src/program.cc b/src/program.cc index 5ae2e26621..07fa1d51aa 100644 --- a/src/program.cc +++ b/src/program.cc @@ -21,9 +21,9 @@ namespace tint { -Program::Program() = default; +Program::Program() : ast_(nodes_.Create()) {} -Program::Program(Program&&) = default; +Program::Program(Program&& rhs) = default; Program& Program::operator=(Program&& rhs) = default; @@ -36,93 +36,35 @@ Program Program::Clone() const { } void Program::Clone(CloneContext* ctx) const { - for (auto* ty : constructed_types_) { - ctx->dst->constructed_types_.emplace_back(ctx->Clone(ty)); + for (auto* ty : AST().ConstructedTypes()) { + ctx->dst->AST().AddConstructedType(ctx->Clone(ty)); } - for (auto* var : global_variables_) { - ctx->dst->global_variables_.emplace_back(ctx->Clone(var)); + for (auto* var : AST().GlobalVariables()) { + ctx->dst->AST().AddGlobalVariable(ctx->Clone(var)); } - for (auto* func : functions_) { - ctx->dst->functions_.emplace_back(ctx->Clone(func)); + for (auto* func : AST().Functions()) { + ctx->dst->AST().Functions().Add(ctx->Clone(func)); } } Symbol Program::RegisterSymbol(const std::string& name) { - return symbol_table_.Register(name); + return symbols_.Register(name); } Symbol Program::GetSymbol(const std::string& name) const { - return symbol_table_.Get(name); + return symbols_.Get(name); } std::string Program::SymbolToName(const Symbol sym) const { - return symbol_table_.NameFor(sym); + return symbols_.NameFor(sym); } bool Program::IsValid() const { - for (auto* var : global_variables_) { - if (var == nullptr || !var->IsValid()) { - return false; - } - } - for (auto* const ty : constructed_types_) { - if (ty == nullptr) { - return false; - } - if (auto* alias = ty->As()) { - if (alias->type() == nullptr) { - return false; - } - if (auto* str = alias->type()->As()) { - if (!str->symbol().IsValid()) { - return false; - } - } - } else if (auto* str = ty->As()) { - if (!str->symbol().IsValid()) { - return false; - } - } else { - return false; - } - } - for (auto* func : functions_) { - if (func == nullptr || !func->IsValid()) { - return false; - } - } - return true; + return ast_->IsValid(); } std::string Program::to_str() const { - std::ostringstream out; - - out << "Module{" << std::endl; - const auto indent = 2; - for (auto* const ty : constructed_types_) { - for (size_t i = 0; i < indent; ++i) { - out << " "; - } - if (auto* alias = ty->As()) { - out << alias->symbol().to_str() << " -> " << alias->type()->type_name() - << std::endl; - if (auto* str = alias->type()->As()) { - str->impl()->to_str(out, indent); - } - } else if (auto* str = ty->As()) { - out << str->symbol().to_str() << " "; - str->impl()->to_str(out, indent); - } - } - for (auto* var : global_variables_) { - var->to_str(out, indent); - } - for (auto* func : functions_) { - func->to_str(out, indent); - } - out << "}" << std::endl; - - return out.str(); + return ast_->to_str(); } } // namespace tint diff --git a/src/program.h b/src/program.h index e232c3b11d..5ba6dfeb4a 100644 --- a/src/program.h +++ b/src/program.h @@ -24,6 +24,7 @@ #include #include "src/ast/function.h" +#include "src/ast/module.h" #include "src/ast/variable.h" #include "src/block_allocator.h" #include "src/symbol_table.h" @@ -36,11 +37,15 @@ namespace tint { /// Represents all the source in a given program. class Program { public: + /// ASTNodes is an alias to BlockAllocator + using ASTNodes = BlockAllocator; + /// Constructor Program(); /// Move constructor - Program(Program&&); + /// @param rhs the Program to move + Program(Program&& rhs); /// Move assignment operator /// @param rhs the Program to move @@ -50,10 +55,28 @@ class Program { /// Destructor ~Program(); + /// @returns a reference to the program's types + const type::Manager& Types() const { return types_; } + + /// @returns a reference to the program's AST nodes storage + const ASTNodes& Nodes() const { return nodes_; } + + /// @returns a reference to the program's AST root Module + const ast::Module& AST() const { return *ast_; } + + /// @returns a reference to the program's AST root Module + ast::Module& AST() { return *ast_; } + + /// @returns a reference to the program's SymbolTable + const SymbolTable& Symbols() const { return symbols_; } + + /// @returns a reference to the program's SymbolTable + SymbolTable& Symbols() { return symbols_; } + /// @return a deep copy of this program Program Clone() const; - /// Clone this program into `ctx->mod` using the provided CloneContext + /// Clone this program into `ctx->dst` using the provided CloneContext /// The program will be cloned in this order: /// * Constructed types /// * Global variables @@ -61,36 +84,6 @@ class Program { /// @param ctx the clone context void Clone(CloneContext* ctx) const; - /// Add a global variable to the program - /// @param var the variable to add - void AddGlobalVariable(ast::Variable* var) { - global_variables_.push_back(var); - } - /// @returns the global variables for the program - const ast::VariableList& global_variables() const { - return global_variables_; - } - - /// @returns the global variables for the program - ast::VariableList& global_variables() { return global_variables_; } - - /// Adds a constructed type to the program. - /// The type must be an alias or a struct. - /// @param type the constructed type to add - void AddConstructedType(type::Type* type) { - constructed_types_.push_back(type); - } - /// @returns the constructed types in the program - const std::vector& constructed_types() const { - return constructed_types_; - } - - /// @returns the functions declared in the translation unit - const ast::FunctionList& Functions() const { return functions_; } - - /// @returns the functions declared in the translation unit - ast::FunctionList& Functions() { return functions_; } - /// @returns true if all required fields in the AST are present. bool IsValid() const; @@ -103,7 +96,7 @@ class Program { /// @returns the node pointer template traits::EnableIfIsType* create(ARGS&&... args) { - return ast_nodes_.Create(std::forward(args)...); + return nodes_.Create(std::forward(args)...); } /// Creates a new type::Type owned by the Program. @@ -122,44 +115,83 @@ class Program { traits::EnableIfIsType* create(ARGS&&... args) { static_assert(std::is_base_of::value, "T does not derive from type::Type"); - return type_mgr_.Get(std::forward(args)...); + return types_.Get(std::forward(args)...); } + /// Add a global variable to the program + /// [DEPRECATED]: Use AST().AddGlobalVariable(var) + /// @param var the variable to add + void AddGlobalVariable(ast::Variable* var) { AST().AddGlobalVariable(var); } + + /// [DEPRECATED]: Use AST().GlobalVariables() + /// @returns the global variables for the program + const ast::VariableList& global_variables() const { + return AST().GlobalVariables(); + } + + /// [DEPRECATED]: Use AST().GlobalVariables() + /// @returns the global variables for the program + ast::VariableList& global_variables() { return AST().GlobalVariables(); } + + /// Adds a constructed type to the program. + /// The type must be an alias or a struct. + /// [DEPRECATED]: Use AST().AddConstructedType(type) + /// @param type the constructed type to add + void AddConstructedType(type::Type* type) { AST().AddConstructedType(type); } + + /// @returns the constructed types in the program + /// [DEPRECATED]: Use AST().ConstructedTypes() + const std::vector& constructed_types() const { + return AST().ConstructedTypes(); + } + + /// @returns the functions declared in the translation unit + /// [DEPRECATED]: Use AST().Functions() + const ast::FunctionList& Functions() const { return AST().Functions(); } + + /// @returns the functions declared in the translation unit + /// [DEPRECATED]: Use AST().Functions() + ast::FunctionList& Functions() { return AST().Functions(); } + /// Returns all the declared types in the program + /// [DEPRECATED]: Use AST().Types().types() /// @returns the mapping from name string to type. const std::unordered_map& types() { - return type_mgr_.types(); + return types_.types(); } /// @returns all the declared nodes in the program - BlockAllocator::View nodes() { return ast_nodes_.Objects(); } + /// [DEPRECATED]: Use Nodes().Objects() + BlockAllocator::ConstView nodes() const { + return Nodes().Objects(); + } /// Registers `name` as a symbol /// @param name the name to register /// @returns the symbol for the `name`. If `name` is already registered the /// previously generated symbol will be returned. + /// [DEPRECATED]: Use Symbols().Register() Symbol RegisterSymbol(const std::string& name); /// Returns the symbol for `name` /// @param name the name to lookup /// @returns the symbol for name or symbol::kInvalid + /// [DEPRECATED]: Use Symbols().Get() Symbol GetSymbol(const std::string& name) const; /// Returns the `name` for `sym` /// @param sym the symbol to retrieve the name for /// @returns the use provided `name` for the symbol or "" if not found + /// [DEPRECATED]: Use Symbols().NameFor() std::string SymbolToName(const Symbol sym) const; private: Program(const Program&) = delete; - SymbolTable symbol_table_; - ast::VariableList global_variables_; - // The constructed types are owned by the type manager - std::vector constructed_types_; - ast::FunctionList functions_; - BlockAllocator ast_nodes_; - type::Manager type_mgr_; + type::Manager types_; + ASTNodes nodes_; + ast::Module* ast_; + SymbolTable symbols_; }; } // namespace tint