Resolver: Generate mapping for ast::Type -> sem::Type
Currently untestable as nothing currently calls Type(const ast::Type* ty). Bug: tint:724 Change-Id: I92dd772acd758b0960a7e9a19f15c91414ab505c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49527 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
f34cb1fe70
commit
fbec46fba9
|
@ -107,6 +107,10 @@ sem::Type* Program::TypeOf(const ast::Expression* expr) const {
|
||||||
return sem ? sem->Type() : nullptr;
|
return sem ? sem->Type() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sem::Type* Program::TypeOf(const ast::Type* type) const {
|
||||||
|
return Sem().Get(type);
|
||||||
|
}
|
||||||
|
|
||||||
std::string Program::to_str(bool demangle) const {
|
std::string Program::to_str(bool demangle) const {
|
||||||
AssertNotMoved();
|
AssertNotMoved();
|
||||||
auto str = ast_->to_str(Sem());
|
auto str = ast_->to_str(Sem());
|
||||||
|
|
|
@ -131,6 +131,12 @@ class Program {
|
||||||
/// expression has no resolved type.
|
/// expression has no resolved type.
|
||||||
sem::Type* TypeOf(const ast::Expression* expr) const;
|
sem::Type* TypeOf(const ast::Expression* expr) const;
|
||||||
|
|
||||||
|
/// Helper for returning the resolved semantic type of the AST type `type`.
|
||||||
|
/// @param expr the AST type
|
||||||
|
/// @return the resolved semantic type for the type, or nullptr if the type
|
||||||
|
/// has no resolved type.
|
||||||
|
const sem::Type* TypeOf(const ast::Type* expr) const;
|
||||||
|
|
||||||
/// @param demangle whether to automatically demangle the symbols in the
|
/// @param demangle whether to automatically demangle the symbols in the
|
||||||
/// returned string
|
/// returned string
|
||||||
/// @returns a string describing this program.
|
/// @returns a string describing this program.
|
||||||
|
|
|
@ -86,11 +86,15 @@ void ProgramBuilder::AssertNotMoved() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sem::Type* ProgramBuilder::TypeOf(ast::Expression* expr) const {
|
sem::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const {
|
||||||
auto* sem = Sem().Get(expr);
|
auto* sem = Sem().Get(expr);
|
||||||
return sem ? sem->Type() : nullptr;
|
return sem ? sem->Type() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sem::Type* ProgramBuilder::TypeOf(const ast::Type* type) const {
|
||||||
|
return Sem().Get(type);
|
||||||
|
}
|
||||||
|
|
||||||
ast::ConstructorExpression* ProgramBuilder::ConstructValueFilledWith(
|
ast::ConstructorExpression* ProgramBuilder::ConstructValueFilledWith(
|
||||||
typ::Type type,
|
typ::Type type,
|
||||||
int elem_value) {
|
int elem_value) {
|
||||||
|
|
|
@ -1788,7 +1788,15 @@ class ProgramBuilder {
|
||||||
/// @param expr the AST expression
|
/// @param expr the AST expression
|
||||||
/// @return the resolved semantic type for the expression, or nullptr if the
|
/// @return the resolved semantic type for the expression, or nullptr if the
|
||||||
/// expression has no resolved type.
|
/// expression has no resolved type.
|
||||||
sem::Type* TypeOf(ast::Expression* expr) const;
|
sem::Type* TypeOf(const ast::Expression* expr) const;
|
||||||
|
|
||||||
|
/// Helper for returning the resolved semantic type of the AST type `type`.
|
||||||
|
/// @note As the Resolver is run when the Program is built, this will only be
|
||||||
|
/// useful for the Resolver itself and tests that use their own Resolver.
|
||||||
|
/// @param expr the AST type
|
||||||
|
/// @return the resolved semantic type for the type, or nullptr if the type
|
||||||
|
/// has no resolved type.
|
||||||
|
const sem::Type* TypeOf(const ast::Type* expr) const;
|
||||||
|
|
||||||
/// Wraps the ast::Literal in a statement. This is used by tests that
|
/// Wraps the ast::Literal in a statement. This is used by tests that
|
||||||
/// construct a partial AST and require the Resolver to reach these
|
/// construct a partial AST and require the Resolver to reach these
|
||||||
|
|
|
@ -274,69 +274,116 @@ bool Resolver::ResolveInternal() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sem::Type* Resolver::Type(const ast::Type* ty) {
|
const sem::Type* Resolver::Type(const ast::Type* ty) {
|
||||||
Mark(ty);
|
Mark(ty);
|
||||||
sem::Type* s = nullptr;
|
auto* s = [&]() -> const sem::Type* {
|
||||||
if (ty->Is<ast::Void>()) {
|
if (ty->Is<ast::Void>()) {
|
||||||
s = builder_->create<sem::Void>();
|
return builder_->create<sem::Void>();
|
||||||
} else if (ty->Is<ast::Bool>()) {
|
|
||||||
s = builder_->create<sem::Bool>();
|
|
||||||
} else if (ty->Is<ast::I32>()) {
|
|
||||||
s = builder_->create<sem::I32>();
|
|
||||||
} else if (ty->Is<ast::U32>()) {
|
|
||||||
s = builder_->create<sem::U32>();
|
|
||||||
} else if (ty->Is<ast::F32>()) {
|
|
||||||
s = builder_->create<sem::F32>();
|
|
||||||
} else if (auto* alias = ty->As<ast::Alias>()) {
|
|
||||||
auto* el = Type(alias->type());
|
|
||||||
s = builder_->create<sem::Alias>(alias->symbol(), el);
|
|
||||||
} else if (auto* access = ty->As<ast::AccessControl>()) {
|
|
||||||
auto* el = Type(access->type());
|
|
||||||
s = builder_->create<sem::AccessControl>(access->access_control(), el);
|
|
||||||
} else if (auto* vec = ty->As<ast::Vector>()) {
|
|
||||||
auto* el = Type(vec->type());
|
|
||||||
s = builder_->create<sem::Vector>(el, vec->size());
|
|
||||||
} else if (auto* mat = ty->As<ast::Matrix>()) {
|
|
||||||
auto* el = Type(mat->type());
|
|
||||||
s = builder_->create<sem::Matrix>(el, mat->rows(), mat->columns());
|
|
||||||
} else if (auto* arr = ty->As<ast::Array>()) {
|
|
||||||
auto* el = Type(arr->type());
|
|
||||||
s = builder_->create<sem::ArrayType>(el, arr->size(), arr->decorations());
|
|
||||||
} else if (auto* ptr = ty->As<ast::Pointer>()) {
|
|
||||||
auto* el = Type(ptr->type());
|
|
||||||
s = builder_->create<sem::Pointer>(el, ptr->storage_class());
|
|
||||||
} else if (auto* str = ty->As<ast::Struct>()) {
|
|
||||||
s = builder_->create<sem::StructType>(const_cast<ast::Struct*>(str));
|
|
||||||
} else if (auto* sampler = ty->As<ast::Sampler>()) {
|
|
||||||
s = builder_->create<sem::Sampler>(sampler->kind());
|
|
||||||
} else if (auto* sampled_tex = ty->As<ast::SampledTexture>()) {
|
|
||||||
auto* el = Type(sampled_tex->type());
|
|
||||||
s = builder_->create<sem::SampledTexture>(sampled_tex->dim(), el);
|
|
||||||
} else if (auto* depth_tex = ty->As<ast::DepthTexture>()) {
|
|
||||||
s = builder_->create<sem::DepthTexture>(depth_tex->dim());
|
|
||||||
} else if (auto* storage_tex = ty->As<ast::StorageTexture>()) {
|
|
||||||
auto* el = Type(storage_tex->type());
|
|
||||||
s = builder_->create<sem::StorageTexture>(storage_tex->dim(),
|
|
||||||
storage_tex->image_format(), el);
|
|
||||||
}
|
}
|
||||||
|
if (ty->Is<ast::Bool>()) {
|
||||||
|
return builder_->create<sem::Bool>();
|
||||||
|
}
|
||||||
|
if (ty->Is<ast::I32>()) {
|
||||||
|
return builder_->create<sem::I32>();
|
||||||
|
}
|
||||||
|
if (ty->Is<ast::U32>()) {
|
||||||
|
return builder_->create<sem::U32>();
|
||||||
|
}
|
||||||
|
if (ty->Is<ast::F32>()) {
|
||||||
|
return builder_->create<sem::F32>();
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Alias>()) {
|
||||||
|
return Type(t->type());
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::AccessControl>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::AccessControl>(t->access_control(),
|
||||||
|
const_cast<sem::Type*>(el));
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Vector>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::Vector>(const_cast<sem::Type*>(el),
|
||||||
|
t->size());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Matrix>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::Matrix>(const_cast<sem::Type*>(el),
|
||||||
|
t->rows(), t->columns());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Array>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::ArrayType>(const_cast<sem::Type*>(el),
|
||||||
|
t->size(), t->decorations());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Pointer>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::Pointer>(const_cast<sem::Type*>(el),
|
||||||
|
t->storage_class());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Struct>()) {
|
||||||
|
return builder_->create<sem::StructType>(const_cast<ast::Struct*>(t));
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::Sampler>()) {
|
||||||
|
return builder_->create<sem::Sampler>(t->kind());
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::SampledTexture>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::SampledTexture>(
|
||||||
|
t->dim(), const_cast<sem::Type*>(el));
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::MultisampledTexture>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::MultisampledTexture>(
|
||||||
|
t->dim(), const_cast<sem::Type*>(el));
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::DepthTexture>()) {
|
||||||
|
return builder_->create<sem::DepthTexture>(t->dim());
|
||||||
|
}
|
||||||
|
if (auto* t = ty->As<ast::StorageTexture>()) {
|
||||||
|
if (auto* el = Type(t->type())) {
|
||||||
|
return builder_->create<sem::StorageTexture>(
|
||||||
|
t->dim(), t->image_format(), const_cast<sem::Type*>(el));
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
TINT_UNREACHABLE(diagnostics_)
|
||||||
|
<< "Unhandled ast::Type: " << ty->TypeInfo().name;
|
||||||
|
return nullptr;
|
||||||
|
}();
|
||||||
|
|
||||||
if (s == nullptr) {
|
if (s == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!Type(s)) {
|
if (!Type(s, ty->source())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
builder_->Sem().Add(ty, s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(crbug.com/tint/724): This method should be replaced by Type(ast::Type*)
|
// TODO(crbug.com/tint/724): This method should be merged into Type(ast::Type*)
|
||||||
bool Resolver::Type(sem::Type* ty) {
|
bool Resolver::Type(const sem::Type* ty, const Source& source /* = {} */) {
|
||||||
ty = ty->UnwrapAliasIfNeeded();
|
ty = ty->UnwrapAliasIfNeeded();
|
||||||
if (auto* str = ty->As<sem::StructType>()) {
|
if (auto* str = ty->As<sem::StructType>()) {
|
||||||
if (!Structure(str)) {
|
if (!Structure(str)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (auto* arr = ty->As<sem::ArrayType>()) {
|
} else if (auto* arr = ty->As<sem::ArrayType>()) {
|
||||||
if (!Array(arr, Source{})) {
|
if (!Array(arr, source)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ class Resolver {
|
||||||
bool Statement(ast::Statement*);
|
bool Statement(ast::Statement*);
|
||||||
bool Statements(const ast::StatementList&);
|
bool Statements(const ast::StatementList&);
|
||||||
bool Switch(ast::SwitchStatement* s);
|
bool Switch(ast::SwitchStatement* s);
|
||||||
bool Type(sem::Type* ty);
|
bool Type(const sem::Type* ty, const Source& source = {});
|
||||||
bool UnaryOp(ast::UnaryOpExpression*);
|
bool UnaryOp(ast::UnaryOpExpression*);
|
||||||
bool VariableDeclStatement(const ast::VariableDeclStatement*);
|
bool VariableDeclStatement(const ast::VariableDeclStatement*);
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ class Resolver {
|
||||||
/// hasn't been constructed already. If an error is raised, nullptr is
|
/// hasn't been constructed already. If an error is raised, nullptr is
|
||||||
/// returned.
|
/// returned.
|
||||||
/// @param ty the ast::Type
|
/// @param ty the ast::Type
|
||||||
sem::Type* Type(const ast::Type* ty);
|
const sem::Type* Type(const ast::Type* ty);
|
||||||
|
|
||||||
/// @returns the semantic information for the array `arr`, building it if it
|
/// @returns the semantic information for the array `arr`, building it if it
|
||||||
/// hasn't been constructed already. If an error is raised, nullptr is
|
/// hasn't been constructed already. If an error is raised, nullptr is
|
||||||
|
|
|
@ -88,7 +88,9 @@ class Info {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<const CastableBase*, const sem::Node*> map;
|
// 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Function;
|
||||||
class MemberAccessorExpression;
|
class MemberAccessorExpression;
|
||||||
class Statement;
|
class Statement;
|
||||||
class StructMember;
|
class StructMember;
|
||||||
|
class Type;
|
||||||
class Variable;
|
class Variable;
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ class Statement;
|
||||||
class Struct;
|
class Struct;
|
||||||
class StructType;
|
class StructType;
|
||||||
class StructMember;
|
class StructMember;
|
||||||
|
class Type;
|
||||||
class Variable;
|
class Variable;
|
||||||
|
|
||||||
/// TypeMappings is a struct that holds undefined `operator()` methods that's
|
/// TypeMappings is a struct that holds undefined `operator()` methods that's
|
||||||
|
@ -58,6 +60,7 @@ struct TypeMappings {
|
||||||
Statement* operator()(ast::Statement*);
|
Statement* operator()(ast::Statement*);
|
||||||
Struct* operator()(sem::StructType*);
|
Struct* operator()(sem::StructType*);
|
||||||
StructMember* operator()(ast::StructMember*);
|
StructMember* operator()(ast::StructMember*);
|
||||||
|
Type* operator()(ast::Type*);
|
||||||
Variable* operator()(ast::Variable*);
|
Variable* operator()(ast::Variable*);
|
||||||
//! @endcond
|
//! @endcond
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue