Add sem::Module

Holds `DependencyOrderedDeclarations()`, which will hold the
sorted dependency-graph ordered list of global declarations.

Bug: tint:1266
Change-Id: I9840fae8689abd214973ea4785f71c3ae2587bbc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79766
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-02-09 23:55:51 +00:00
parent 597fc4cdbe
commit a52be6c9ec
9 changed files with 179 additions and 42 deletions

View File

@ -398,6 +398,7 @@ libtint_source_set("libtint_core_all_src") {
"sem/info.h",
"sem/loop_statement.h",
"sem/matrix_type.h",
"sem/module.h",
"sem/multisampled_texture_type.h",
"sem/node.h",
"sem/parameter_usage.h",
@ -574,6 +575,8 @@ libtint_source_set("libtint_sem_src") {
"sem/matrix_type.cc",
"sem/matrix_type.h",
"sem/member_accessor_expression.cc",
"sem/module.cc",
"sem/module.h",
"sem/multisampled_texture_type.cc",
"sem/multisampled_texture_type.h",
"sem/node.cc",

View File

@ -285,6 +285,8 @@ set(TINT_LIB_SRCS
sem/pipeline_stage_set.h
sem/node.cc
sem/node.h
sem/module.cc
sem/module.h
sem/sampler_texture_pair.h
sem/statement.cc
sem/struct.cc

View File

@ -34,16 +34,8 @@ Module::Module(ProgramID pid,
if (decl == nullptr) {
continue;
}
Switch(
decl, //
[&](const ast::TypeDecl* type) { type_decls_.push_back(type); },
[&](const Function* func) { functions_.push_back(func); },
[&](const Variable* var) { global_variables_.push_back(var); },
[&](Default) {
diag::List diagnostics;
TINT_ICE(AST, diagnostics) << "Unknown global declaration type";
});
diag::List diags;
BinGlobalDeclaration(decl, diags);
}
}
@ -58,6 +50,33 @@ const ast::TypeDecl* Module::LookupType(Symbol name) const {
return nullptr;
}
void Module::AddGlobalDeclaration(const tint::ast::Node* decl) {
diag::List diags;
BinGlobalDeclaration(decl, diags);
global_declarations_.emplace_back(decl);
}
void Module::BinGlobalDeclaration(const tint::ast::Node* decl,
diag::List& diags) {
Switch(
decl, //
[&](const ast::TypeDecl* type) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
type_decls_.push_back(type);
},
[&](const Function* func) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
functions_.push_back(func);
},
[&](const Variable* var) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
global_variables_.push_back(var);
},
[&](Default) {
TINT_ICE(AST, diags) << "Unknown global declaration type";
});
}
void Module::AddGlobalVariable(const ast::Variable* var) {
TINT_ASSERT(AST, var);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
@ -100,24 +119,7 @@ void Module::Copy(CloneContext* ctx, const Module* src) {
<< "src global declaration was nullptr";
continue;
}
Switch(
decl,
[&](const ast::TypeDecl* type) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
type_decls_.push_back(type);
},
[&](const Function* func) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
functions_.push_back(func);
},
[&](const Variable* var) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
global_variables_.push_back(var);
},
[&](Default) {
TINT_ICE(AST, ctx->dst->Diagnostics())
<< "Unknown global declaration type";
});
BinGlobalDeclaration(decl, ctx->dst->Diagnostics());
}
}

View File

@ -47,7 +47,7 @@ class Module : public Castable<Module, Node> {
/// Destructor
~Module() override;
/// @returns the ordered global declarations for the translation unit
/// @returns the declaration-ordered global declarations for the module
const std::vector<const Node*>& GlobalDeclarations() const {
return global_declarations_;
}
@ -67,10 +67,14 @@ class Module : public Castable<Module, Node> {
return false;
}
/// @returns the global variables for the translation unit
/// Adds a global declaration to the Builder.
/// @param decl the declaration to add
void AddGlobalDeclaration(const tint::ast::Node* decl);
/// @returns the global variables for the module
const VariableList& GlobalVariables() const { return global_variables_; }
/// @returns the global variables for the translation unit
/// @returns the global variables for the module
VariableList& GlobalVariables() { return global_variables_; }
/// Adds a type declaration to the Builder.
@ -81,14 +85,14 @@ class Module : public Castable<Module, Node> {
/// @param name the name of the type to search for
const TypeDecl* LookupType(Symbol name) const;
/// @returns the declared types in the translation unit
/// @returns the declared types in the module
const std::vector<const TypeDecl*>& TypeDecls() const { return type_decls_; }
/// Add a function to the Builder
/// @param func the function to add
void AddFunction(const Function* func);
/// @returns the functions declared in the translation unit
/// @returns the functions declared in the module
const FunctionList& Functions() const { return functions_; }
/// Clones this node and all transitive child nodes using the `CloneContext`
@ -103,6 +107,12 @@ class Module : public Castable<Module, Node> {
void Copy(CloneContext* ctx, const Module* src);
private:
/// Adds `decl` to either:
/// * #global_declarations_
/// * #type_decls_
/// * #functions_
void BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags);
std::vector<const Node*> global_declarations_;
std::vector<const TypeDecl*> type_decls_;
FunctionList functions_;

View File

@ -60,6 +60,7 @@
#include "src/sem/if_statement.h"
#include "src/sem/loop_statement.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/pointer_type.h"
#include "src/sem/reference_type.h"
@ -99,6 +100,10 @@ bool Resolver::Resolve() {
return false;
}
// Create the semantic module
builder_->Sem().SetModule(
builder_->create<sem::Module>(dependencies_.ordered_globals));
bool result = ResolveInternal();
if (!result && !diagnostics_.contains_errors()) {

View File

@ -39,6 +39,7 @@
#include "src/sem/call.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/reference_type.h"
#include "src/sem/sampled_texture_type.h"
#include "src/sem/statement.h"
@ -2161,6 +2162,28 @@ TEST_F(ResolverTest, TextureSampler_TextureDimensions) {
EXPECT_TRUE(pairs[0].first != nullptr);
EXPECT_TRUE(pairs[0].second == nullptr);
}
TEST_F(ResolverTest, ModuleDependencyOrderedDeclarations) {
auto* f0 = Func("f0", {}, ty.void_(), {});
auto* v0 = Global("v0", ty.i32(), ast::StorageClass::kPrivate);
auto* a0 = Alias("a0", ty.i32());
auto* s0 = Structure("s0", {Member("m", ty.i32())});
auto* f1 = Func("f1", {}, ty.void_(), {});
auto* v1 = Global("v1", ty.i32(), ast::StorageClass::kPrivate);
auto* a1 = Alias("a1", ty.i32());
auto* s1 = Structure("s1", {Member("m", ty.i32())});
auto* f2 = Func("f2", {}, ty.void_(), {});
auto* v2 = Global("v2", ty.i32(), ast::StorageClass::kPrivate);
auto* a2 = Alias("a2", ty.i32());
auto* s2 = Structure("s2", {Member("m", ty.i32())});
EXPECT_TRUE(r()->Resolve()) << r()->error();
ASSERT_NE(Sem().Module(), nullptr);
EXPECT_THAT(Sem().Module()->DependencyOrderedDeclarations(),
ElementsAre(f0, v0, a0, s0, f1, v1, a1, s1, f2, v2, a2, s2));
}
} // namespace
} // namespace resolver
} // namespace tint

View File

@ -22,8 +22,10 @@
#include "src/sem/node.h"
#include "src/sem/type_mappings.h"
namespace tint {
namespace sem {
namespace tint::sem {
// Forward declarations
class Module;
/// Info holds all the resolved semantic information for a Program.
class Info {
@ -60,8 +62,8 @@ class Info {
typename AST_OR_TYPE = CastableBase,
typename RESULT = GetResultType<SEM, AST_OR_TYPE>>
const RESULT* Get(const AST_OR_TYPE* node) const {
auto it = map.find(node);
if (it == map.end()) {
auto it = map_.find(node);
if (it == map_.end()) {
return nullptr;
}
return As<RESULT>(it->second);
@ -76,7 +78,7 @@ class Info {
const SemanticNodeTypeFor<AST_OR_TYPE>* sem_node) {
// Check there's no semantic info already existing for the node
TINT_ASSERT(Semantic, Get(node) == nullptr);
map.emplace(node, sem_node);
map_.emplace(node, sem_node);
}
/// Wrap returns a new Info created with the contents of `inner`.
@ -88,17 +90,26 @@ class Info {
/// @return the Info that wraps `inner`
static Info Wrap(const Info& inner) {
Info out;
out.map = inner.map;
out.map_ = inner.map_;
out.module_ = inner.module_;
return out;
}
/// Assigns the semantic module.
/// @param module the module to assign.
void SetModule(sem::Module* module) { module_ = module; }
/// @returns the semantic module.
const sem::Module* Module() const { return module_; }
private:
// TODO(crbug.com/tint/724): Once finished, this map should be:
// std::unordered_map<const ast::Node*, const sem::Node*>
std::unordered_map<const CastableBase*, const CastableBase*> map;
std::unordered_map<const CastableBase*, const CastableBase*> map_;
// The semantic module
sem::Module* module_ = nullptr;
};
} // namespace sem
} // namespace tint
} // namespace tint::sem
#endif // SRC_SEM_INFO_H_

29
src/sem/module.cc Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2022 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.
#include "src/sem/module.h"
#include <utility>
#include <vector>
TINT_INSTANTIATE_TYPEINFO(tint::sem::Module);
namespace tint::sem {
Module::Module(std::vector<const ast::Node*> dep_ordered_decls)
: dep_ordered_decls_(std::move(dep_ordered_decls)) {}
Module::~Module() = default;
} // namespace tint::sem

52
src/sem/module.h Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2022 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_SEM_MODULE_H_
#define SRC_SEM_MODULE_H_
#include <vector>
#include "src/sem/node.h"
// Forward declarations
namespace tint::ast {
class Node;
class Module;
} // namespace tint::ast
namespace tint::sem {
/// Module holds the top-level semantic types, functions and global variables
/// used by a Program.
class Module : public Castable<Module, Node> {
public:
/// Constructor
/// @param dep_ordered_decls the dependency-ordered module-scope declarations
explicit Module(std::vector<const ast::Node*> dep_ordered_decls);
/// Destructor
~Module() override;
/// @returns the dependency-ordered global declarations for the module
const std::vector<const ast::Node*>& DependencyOrderedDeclarations() const {
return dep_ordered_decls_;
}
private:
const std::vector<const ast::Node*> dep_ordered_decls_;
};
} // namespace tint::sem
#endif // SRC_SEM_MODULE_H_