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 <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2021-01-26 16:57:10 +00:00
parent 9f7a414505
commit a07396a13c
6 changed files with 283 additions and 118 deletions

View File

@ -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 <sstream>
#include <string>
#include <utility>
#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<type::Type*> 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<type::Alias>()) {
if (alias->type() == nullptr) {
return false;
}
if (auto* str = alias->type()->As<type::Struct>()) {
if (!str->symbol().IsValid()) {
return false;
}
}
} else if (auto* str = ty->As<type::Struct>()) {
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<Module>(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<type::Alias>()) {
out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
<< std::endl;
if (auto* str = alias->type()->As<type::Struct>()) {
str->impl()->to_str(out, indent);
}
} else if (auto* str = ty->As<type::Struct>()) {
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

View File

@ -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 <string>
#include <vector>
#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<Module, Node> {
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<type::Type*> 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<type::Type*>& 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<type::Type*> constructed_types_;
FunctionList functions_;
VariableList global_variables_;
};
} // namespace ast
} // namespace tint

View File

@ -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

View File

@ -19,6 +19,7 @@
#include <unordered_map>
#include <vector>
#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`.

View File

@ -21,9 +21,9 @@
namespace tint {
Program::Program() = default;
Program::Program() : ast_(nodes_.Create<ast::Module>()) {}
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<type::Alias>()) {
if (alias->type() == nullptr) {
return false;
}
if (auto* str = alias->type()->As<type::Struct>()) {
if (!str->symbol().IsValid()) {
return false;
}
}
} else if (auto* str = ty->As<type::Struct>()) {
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<type::Alias>()) {
out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
<< std::endl;
if (auto* str = alias->type()->As<type::Struct>()) {
str->impl()->to_str(out, indent);
}
} else if (auto* str = ty->As<type::Struct>()) {
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

View File

@ -24,6 +24,7 @@
#include <vector>
#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<ast::Node>
using ASTNodes = BlockAllocator<ast::Node>;
/// 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<type::Type*>& 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 <typename T, typename... ARGS>
traits::EnableIfIsType<T, ast::Node>* create(ARGS&&... args) {
return ast_nodes_.Create<T>(std::forward<ARGS>(args)...);
return nodes_.Create<T>(std::forward<ARGS>(args)...);
}
/// Creates a new type::Type owned by the Program.
@ -122,44 +115,83 @@ class Program {
traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
static_assert(std::is_base_of<type::Type, T>::value,
"T does not derive from type::Type");
return type_mgr_.Get<T>(std::forward<ARGS>(args)...);
return types_.Get<T>(std::forward<ARGS>(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<type::Type*>& 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<std::string, type::Type*>& types() {
return type_mgr_.types();
return types_.types();
}
/// @returns all the declared nodes in the program
BlockAllocator<ast::Node>::View nodes() { return ast_nodes_.Objects(); }
/// [DEPRECATED]: Use Nodes().Objects()
BlockAllocator<ast::Node>::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<type::Type*> constructed_types_;
ast::FunctionList functions_;
BlockAllocator<ast::Node> ast_nodes_;
type::Manager type_mgr_;
type::Manager types_;
ASTNodes nodes_;
ast::Module* ast_;
SymbolTable symbols_;
};
} // namespace tint