tint/resolver: Formatting

Change-Id: I9580a9bad5b1f281d14ee1c1fba38c18d9cff610
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105402
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2022-10-11 20:01:52 +00:00 committed by Dawn LUCI CQ
parent f9ed9d3a63
commit feb447d9dc
1 changed files with 62 additions and 86 deletions

View File

@ -344,8 +344,8 @@ bool Validator::VariableInitializer(const ast::Variable* v,
break; // Allowed an initializer break; // Allowed an initializer
default: default:
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
// Optionally has an initializer expression, if the variable is in the // Optionally has an initializer expression, if the variable is in the private or
// private or function address spacees. // function address spacees.
AddError("var of address space '" + utils::ToString(address_space) + AddError("var of address space '" + utils::ToString(address_space) +
"' cannot have an initializer. var initializers are only " "' cannot have an initializer. var initializers are only "
"supported for the address spacees " "supported for the address spacees "
@ -440,9 +440,8 @@ bool Validator::AddressSpaceLayout(const sem::Type* store_ty,
return false; return false;
} }
// For uniform buffers, validate that the number of bytes between the // For uniform buffers, validate that the number of bytes between the previous member of
// previous member of type struct and the current is a multiple of 16 // type struct and the current is a multiple of 16 bytes.
// bytes.
auto* const prev_member = (i == 0) ? nullptr : str->Members()[i - 1]; auto* const prev_member = (i == 0) ? nullptr : str->Members()[i - 1];
if (prev_member && is_uniform_struct(prev_member->Type())) { if (prev_member && is_uniform_struct(prev_member->Type())) {
const uint32_t prev_to_curr_offset = m->Offset() - prev_member->Offset(); const uint32_t prev_to_curr_offset = m->Offset() - prev_member->Offset();
@ -469,24 +468,22 @@ bool Validator::AddressSpaceLayout(const sem::Type* store_ty,
} }
} }
// For uniform buffer array members, validate that array elements are // For uniform buffer array members, validate that array elements are aligned to 16 bytes
// aligned to 16 bytes
if (auto* arr = store_ty->As<sem::Array>()) { if (auto* arr = store_ty->As<sem::Array>()) {
// Recurse into the element type. // Recurse into the element type.
// TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested // TODO(crbug.com/tint/1388): Ideally we'd pass the source for nested element type here, but
// element type here, but we can't easily get that from the semantic node. // we can't easily get that from the semantic node. We should consider recursing through the
// We should consider recursing through the AST type nodes instead. // AST type nodes instead.
if (!AddressSpaceLayout(arr->ElemType(), address_space, source, layouts)) { if (!AddressSpaceLayout(arr->ElemType(), address_space, source, layouts)) {
return false; return false;
} }
if (address_space == ast::AddressSpace::kUniform) { if (address_space == ast::AddressSpace::kUniform) {
// We already validated that this array member is itself aligned to 16 // We already validated that this array member is itself aligned to 16 bytes above, so
// bytes above, so we only need to validate that stride is a multiple // we only need to validate that stride is a multiple of 16 bytes.
// of 16 bytes.
if (arr->Stride() % 16 != 0) { if (arr->Stride() % 16 != 0) {
// Since WGSL has no stride attribute, try to provide a useful hint // Since WGSL has no stride attribute, try to provide a useful hint for how the
// for how the shader author can resolve the issue. // shader author can resolve the issue.
std::string hint; std::string hint;
if (arr->ElemType()->is_scalar()) { if (arr->ElemType()->is_scalar()) {
hint = hint =
@ -622,8 +619,8 @@ bool Validator::GlobalVariable(
} }
// https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration // https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration
// The access mode always has a default, and except for variables in the // The access mode always has a default, and except for variables in the storage address
// storage address space, must not be written. // space, must not be written.
if (var->declared_access != ast::Access::kUndefined) { if (var->declared_access != ast::Access::kUndefined) {
if (global->AddressSpace() == ast::AddressSpace::kStorage) { if (global->AddressSpace() == ast::AddressSpace::kStorage) {
// The access mode for the storage address space can only be 'read' or // The access mode for the storage address space can only be 'read' or
@ -684,8 +681,7 @@ bool Validator::GlobalVariable(
case ast::AddressSpace::kStorage: case ast::AddressSpace::kStorage:
case ast::AddressSpace::kHandle: { case ast::AddressSpace::kHandle: {
// https://gpuweb.github.io/gpuweb/wgsl/#resource-interface // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
// Each resource variable must be declared with both group and binding // Each resource variable must be declared with both group and binding attributes.
// attributes.
if (!decl->HasBindingPoint()) { if (!decl->HasBindingPoint()) {
AddError("resource variables require @group and @binding attributes", decl->source); AddError("resource variables require @group and @binding attributes", decl->source);
return false; return false;
@ -709,8 +705,8 @@ bool Validator::GlobalVariable(
} }
// https://gpuweb.github.io/gpuweb/wgsl/#atomic-types // https://gpuweb.github.io/gpuweb/wgsl/#atomic-types
// Atomic types may only be instantiated by variables in the workgroup storage // Atomic types may only be instantiated by variables in the workgroup storage class or by storage
// class or by storage buffer variables with a read_write access mode. // buffer variables with a read_write access mode.
bool Validator::AtomicVariable( bool Validator::AtomicVariable(
const sem::Variable* var, const sem::Variable* var,
std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const { std::unordered_map<const sem::Type*, const Source&> atomic_composite_info) const {
@ -763,9 +759,8 @@ bool Validator::Var(const sem::Variable* v) const {
if (storage_ty->is_handle() && var->declared_address_space != ast::AddressSpace::kNone) { if (storage_ty->is_handle() && var->declared_address_space != ast::AddressSpace::kNone) {
// https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
// If the store type is a texture type or a sampler type, then the // If the store type is a texture type or a sampler type, then the variable declaration must
// variable declaration must not have a address space attribute. The // not have a address space attribute. The address space will always be handle.
// address space will always be handle.
AddError( AddError(
"variables of type '" + sem_.TypeNameOf(storage_ty) + "' must not have a address space", "variables of type '" + sem_.TypeNameOf(storage_ty) + "' must not have a address space",
var->source); var->source);
@ -1127,10 +1122,10 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
auto* decl = func->Declaration(); auto* decl = func->Declaration();
// Use a lambda to validate the entry point attributes for a type. // Use a lambda to validate the entry point attributes for a type.
// Persistent state is used to track which builtins and locations have // Persistent state is used to track which builtins and locations have already been seen, in
// already been seen, in order to catch conflicts. // order to catch conflicts.
// TODO(jrprice): This state could be stored in sem::Function instead, and // TODO(jrprice): This state could be stored in sem::Function instead, and then passed to
// then passed to sem::Function since it would be useful there too. // sem::Function since it would be useful there too.
std::unordered_set<ast::BuiltinValue> builtins; std::unordered_set<ast::BuiltinValue> builtins;
std::unordered_set<uint32_t> locations; std::unordered_set<uint32_t> locations;
enum class ParamOrRetType { enum class ParamOrRetType {
@ -1145,8 +1140,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
bool is_struct_member, bool is_struct_member,
std::optional<uint32_t> location) { std::optional<uint32_t> location) {
// Temporally forbid using f16 types in entry point IO. // Temporally forbid using f16 types in entry point IO.
// TODO(tint:1473, tint:1502): Remove this error after f16 is supported in entry point // TODO(tint:1473, tint:1502): Remove this error after f16 is supported in entry point IO.
// IO.
if (Is<sem::F16>(sem::Type::DeepestElementOf(ty))) { if (Is<sem::F16>(sem::Type::DeepestElementOf(ty))) {
AddError("entry point IO of f16 types is not implemented yet", source); AddError("entry point IO of f16 types is not implemented yet", source);
return false; return false;
@ -1324,9 +1318,8 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
} }
} }
// Clear IO sets after parameter validation. Builtin and location attributes // Clear IO sets after parameter validation. Builtin and location attributes in return types
// in return types should be validated independently from those used in // should be validated independently from those used in parameters.
// parameters.
builtins.clear(); builtins.clear();
locations.clear(); locations.clear();
@ -1352,9 +1345,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
} }
} }
if (!found) { if (!found) {
AddError( AddError("a vertex shader must include the 'position' builtin in its return type",
"a vertex shader must include the 'position' builtin in its return "
"type",
decl->source); decl->source);
return false; return false;
} }
@ -1362,9 +1353,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
if (decl->PipelineStage() == ast::PipelineStage::kCompute) { if (decl->PipelineStage() == ast::PipelineStage::kCompute) {
if (!ast::HasAttribute<ast::WorkgroupAttribute>(decl->attributes)) { if (!ast::HasAttribute<ast::WorkgroupAttribute>(decl->attributes)) {
AddError( AddError("a compute shader must include 'workgroup_size' in its attributes",
"a compute shader must include 'workgroup_size' in its "
"attributes",
decl->source); decl->source);
return false; return false;
} }
@ -1385,16 +1374,14 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
IsValidationEnabled(res.first->second->attributes, IsValidationEnabled(res.first->second->attributes,
ast::DisabledValidation::kBindingPointCollision)) { ast::DisabledValidation::kBindingPointCollision)) {
// https://gpuweb.github.io/gpuweb/wgsl/#resource-interface // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
// Bindings must not alias within a shader stage: two different // Bindings must not alias within a shader stage: two different variables in the
// variables in the resource interface of a given shader must not have // resource interface of a given shader must not have the same group and binding values,
// the same group and binding values, when considered as a pair of // when considered as a pair of values.
// values.
auto func_name = symbols_.NameFor(decl->symbol); auto func_name = symbols_.NameFor(decl->symbol);
AddError("entry point '" + func_name + AddError(
"' references multiple variables that use the " "entry point '" + func_name +
"same resource binding @group(" + "' references multiple variables that use the same resource binding @group(" +
std::to_string(bp.group) + "), @binding(" + std::to_string(bp.binding) + std::to_string(bp.group) + "), @binding(" + std::to_string(bp.binding) + ")",
")",
var_decl->source); var_decl->source);
AddNote("first resource binding usage declared here", res.first->second->source); AddNote("first resource binding usage declared here", res.first->second->source);
return false; return false;
@ -1453,9 +1440,9 @@ bool Validator::BreakStatement(const sem::Statement* stmt,
if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, current_statement)) { if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, current_statement)) {
auto fail = [&](const char* note_msg, const Source& note_src) { auto fail = [&](const char* note_msg, const Source& note_src) {
constexpr const char* kErrorMsg = constexpr const char* kErrorMsg =
"break statement in a continuing block must be the single statement " "break statement in a continuing block must be the single statement of an if "
"of an if statement's true or false block, and that if statement " "statement's true or false block, and that if statement must be the last statement "
"must be the last statement of the continuing block"; "of the continuing block";
AddError(kErrorMsg, stmt->Declaration()->source); AddError(kErrorMsg, stmt->Declaration()->source);
AddNote(note_msg, note_src); AddNote(note_msg, note_src);
return false; return false;
@ -1491,15 +1478,14 @@ bool Validator::BreakStatement(const sem::Statement* stmt,
if (if_stmt->Parent()->Declaration() != continuing) { if (if_stmt->Parent()->Declaration() != continuing) {
return fail( return fail(
"if statement containing break statement is not directly in " "if statement containing break statement is not directly in continuing block",
"continuing block",
if_stmt->Declaration()->source); if_stmt->Declaration()->source);
} }
if (auto* cont_block = continuing->As<ast::BlockStatement>()) { if (auto* cont_block = continuing->As<ast::BlockStatement>()) {
if (if_stmt->Declaration() != cont_block->Last()) { if (if_stmt->Declaration() != cont_block->Last()) {
return fail( return fail(
"if statement containing break statement is not the last " "if statement containing break statement is not the last statement of the "
"statement of the continuing block", "continuing block",
if_stmt->Declaration()->source); if_stmt->Declaration()->source);
} }
} }
@ -1570,9 +1556,7 @@ bool Validator::FallthroughStatement(const sem::Statement* stmt) const {
if (c->Declaration() != s->Declaration()->body.Back()) { if (c->Declaration() != s->Declaration()->body.Back()) {
return true; return true;
} }
AddError( AddError("a fallthrough statement must not be used in the last switch case",
"a fallthrough statement must not be used in the last switch "
"case",
stmt->Declaration()->source); stmt->Declaration()->source);
return false; return false;
} }
@ -1826,8 +1810,8 @@ bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_stat
IsValidationEnabled(param->Declaration()->attributes, IsValidationEnabled(param->Declaration()->attributes,
ast::DisabledValidation::kIgnoreInvalidPointerArgument)) { ast::DisabledValidation::kIgnoreInvalidPointerArgument)) {
AddError( AddError(
"expected an address-of expression of a variable identifier " "expected an address-of expression of a variable identifier expression or a "
"expression or a function parameter", "function parameter",
arg_expr->source); arg_expr->source);
return false; return false;
} }
@ -1886,8 +1870,7 @@ bool Validator::StructureConstructor(const ast::CallExpression* ctor,
auto* value_ty = sem_.TypeOf(value); auto* value_ty = sem_.TypeOf(value);
if (member->Type() != value_ty->UnwrapRef()) { if (member->Type() != value_ty->UnwrapRef()) {
AddError( AddError(
"type in struct constructor does not match struct member type: " "type in struct constructor does not match struct member type: expected '" +
"expected '" +
sem_.TypeNameOf(member->Type()) + "', found '" + sem_.TypeNameOf(value_ty) + sem_.TypeNameOf(member->Type()) + "', found '" + sem_.TypeNameOf(value_ty) +
"'", "'",
value->source); value->source);
@ -2140,9 +2123,8 @@ bool Validator::ArrayStrideAttribute(const ast::StrideAttribute* attr,
// at least the size of the element type, and be a multiple of the // at least the size of the element type, and be a multiple of the
// element type's alignment value. // element type's alignment value.
AddError( AddError(
"arrays decorated with the stride attribute must have a stride " "arrays decorated with the stride attribute must have a stride that is at least the "
"that is at least the size of the element type, and be a multiple " "size of the element type, and be a multiple of the element type's alignment value",
"of the element type's alignment value",
attr->source); attr->source);
return false; return false;
} }
@ -2189,8 +2171,7 @@ bool Validator::Structure(const sem::Struct* str, ast::PipelineStage stage) cons
} }
} else if (!IsFixedFootprint(member->Type())) { } else if (!IsFixedFootprint(member->Type())) {
AddError( AddError(
"a struct that contains a runtime array cannot be nested inside " "a struct that contains a runtime array cannot be nested inside another struct",
"another struct",
member->Declaration()->source); member->Declaration()->source);
return false; return false;
} }
@ -2283,8 +2264,8 @@ bool Validator::LocationAttribute(const ast::LocationAttribute* loc_attr,
AddError("cannot apply 'location' attribute to declaration of type '" + invalid_type + "'", AddError("cannot apply 'location' attribute to declaration of type '" + invalid_type + "'",
source); source);
AddNote( AddNote(
"'location' attribute must only be applied to declarations of " "'location' attribute must only be applied to declarations of numeric scalar or "
"numeric scalar or numeric vector type", "numeric vector type",
loc_attr->source); loc_attr->source);
return false; return false;
} }
@ -2304,9 +2285,7 @@ bool Validator::Return(const ast::ReturnStatement* ret,
const sem::Type* ret_type, const sem::Type* ret_type,
sem::Statement* current_statement) const { sem::Statement* current_statement) const {
if (func_type->UnwrapRef() != ret_type) { if (func_type->UnwrapRef() != ret_type) {
AddError( AddError("return statement type must match its function return type, returned '" +
"return statement type must match its function "
"return type, returned '" +
sem_.TypeNameOf(ret_type) + "', expected '" + sem_.TypeNameOf(func_type) + "'", sem_.TypeNameOf(ret_type) + "', expected '" + sem_.TypeNameOf(func_type) + "'",
ret->source); ret->source);
return false; return false;
@ -2327,9 +2306,7 @@ bool Validator::Return(const ast::ReturnStatement* ret,
bool Validator::SwitchStatement(const ast::SwitchStatement* s) { bool Validator::SwitchStatement(const ast::SwitchStatement* s) {
auto* cond_ty = sem_.TypeOf(s->condition)->UnwrapRef(); auto* cond_ty = sem_.TypeOf(s->condition)->UnwrapRef();
if (!cond_ty->is_integer_scalar()) { if (!cond_ty->is_integer_scalar()) {
AddError( AddError("switch statement selector expression must be of a scalar integer type",
"switch statement selector expression must be of a "
"scalar integer type",
s->condition->source); s->condition->source);
return false; return false;
} }
@ -2351,8 +2328,7 @@ bool Validator::SwitchStatement(const ast::SwitchStatement* s) {
for (auto* selector : case_stmt->selectors) { for (auto* selector : case_stmt->selectors) {
if (cond_ty != sem_.TypeOf(selector)) { if (cond_ty != sem_.TypeOf(selector)) {
AddError( AddError(
"the case selector values must have the same " "the case selector values must have the same type as the selector expression.",
"type as the selector expression.",
case_stmt->source); case_stmt->source);
return false; return false;
} }
@ -2397,8 +2373,8 @@ bool Validator::Assignment(const ast::Statement* a, const sem::Type* rhs_ty) con
if (!ty->IsConstructible() && if (!ty->IsConstructible() &&
!ty->IsAnyOf<sem::Pointer, sem::Texture, sem::Sampler, sem::AbstractNumeric>()) { !ty->IsAnyOf<sem::Pointer, sem::Texture, sem::Sampler, sem::AbstractNumeric>()) {
AddError("cannot assign '" + sem_.TypeNameOf(rhs_ty) + AddError("cannot assign '" + sem_.TypeNameOf(rhs_ty) +
"' to '_'. '_' can only be assigned a constructible, pointer, " "' to '_'. '_' can only be assigned a constructible, pointer, texture or "
"texture or sampler type", "sampler type",
rhs->source); rhs->source);
return false; return false;
} }