diag: Add System enumerator to all diagnostics

Describes what Tint system raised the diagnostic.

Use this information in the fuzzers to distinguish between expected and unexpected failure cases in the Transform fuzzer tests.

Fixed: chromium:1206407
Fixed: chromium:1207154
Change-Id: I3b807acafe384a2fc363d2a4165a29693450b3cf
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55254
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
Ben Clayton 2021-06-24 11:27:36 +00:00 committed by Tint LUCI CQ
parent 261643bb9f
commit ffd28e2e1a
94 changed files with 1005 additions and 902 deletions

View File

@ -35,12 +35,13 @@ namespace {
__builtin_trap(); __builtin_trap();
} }
[[noreturn]] void ValidityErrorReporter() { [[noreturn]] void ValidityErrorReporter(const tint::diag::List& diags) {
auto printer = tint::diag::Printer::create(stderr, true); auto printer = tint::diag::Printer::create(stderr, true);
printer->write( printer->write(
"Fuzzing detected valid input program being transformed into an invalid " "Fuzzing detected valid input program being transformed into an invalid "
"output progam\n", "output progam\n",
{diag::Color::kRed, true}); {diag::Color::kRed, true});
tint::diag::Formatter().format(diags, printer.get());
__builtin_trap(); __builtin_trap();
} }
@ -258,7 +259,14 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) {
if (transform_manager_) { if (transform_manager_) {
auto out = transform_manager_->Run(&program, transform_inputs_); auto out = transform_manager_->Run(&program, transform_inputs_);
if (!out.program.IsValid()) { if (!out.program.IsValid()) {
ValidityErrorReporter(); // Transforms can produce error messages for bad input.
// Catch ICEs and errors from non transform systems.
for (auto diag : out.program.Diagnostics()) {
if (diag.severity > diag::Severity::Error ||
diag.system != diag::System::Transform) {
ValidityErrorReporter(out.program.Diagnostics());
}
}
} }
program = std::move(out.program); program = std::move(out.program);

View File

@ -28,7 +28,7 @@ Alias::Alias(ProgramID program_id,
: Base(program_id, source, name), : Base(program_id, source, name),
subtype_(subtype), subtype_(subtype),
type_name_("__alias_" + name.to_str() + subtype->type_name()) { type_name_("__alias_" + name.to_str() + subtype->type_name()) {
TINT_ASSERT(subtype_); TINT_ASSERT(AST, subtype_);
} }
Alias::Alias(Alias&&) = default; Alias::Alias(Alias&&) = default;

View File

@ -38,7 +38,7 @@ Array::Array(Array&&) = default;
Array::~Array() = default; Array::~Array() = default;
std::string Array::type_name() const { std::string Array::type_name() const {
TINT_ASSERT(subtype_); TINT_ASSERT(AST, subtype_);
std::string type_name = "__array" + subtype_->type_name(); std::string type_name = "__array" + subtype_->type_name();
if (!IsRuntimeArray()) { if (!IsRuntimeArray()) {

View File

@ -26,10 +26,10 @@ ArrayAccessorExpression::ArrayAccessorExpression(ProgramID program_id,
Expression* array, Expression* array,
Expression* idx_expr) Expression* idx_expr)
: Base(program_id, source), array_(array), idx_expr_(idx_expr) { : Base(program_id, source), array_(array), idx_expr_(idx_expr) {
TINT_ASSERT(array_); TINT_ASSERT(AST, array_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(array_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, array_, program_id);
TINT_ASSERT(idx_expr_); TINT_ASSERT(AST, idx_expr_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(idx_expr_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, idx_expr_, program_id);
} }
ArrayAccessorExpression::ArrayAccessorExpression(ArrayAccessorExpression&&) = ArrayAccessorExpression::ArrayAccessorExpression(ArrayAccessorExpression&&) =

View File

@ -26,10 +26,10 @@ AssignmentStatement::AssignmentStatement(ProgramID program_id,
Expression* lhs, Expression* lhs,
Expression* rhs) Expression* rhs)
: Base(program_id, source), lhs_(lhs), rhs_(rhs) { : Base(program_id, source), lhs_(lhs), rhs_(rhs) {
TINT_ASSERT(lhs_); TINT_ASSERT(AST, lhs_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(lhs_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs_, program_id);
TINT_ASSERT(rhs_); TINT_ASSERT(AST, rhs_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(rhs_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs_, program_id);
} }
AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default; AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;

View File

@ -27,11 +27,11 @@ BinaryExpression::BinaryExpression(ProgramID program_id,
Expression* lhs, Expression* lhs,
Expression* rhs) Expression* rhs)
: Base(program_id, source), op_(op), lhs_(lhs), rhs_(rhs) { : Base(program_id, source), op_(op), lhs_(lhs), rhs_(rhs) {
TINT_ASSERT(lhs_); TINT_ASSERT(AST, lhs_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(lhs_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs_, program_id);
TINT_ASSERT(rhs_); TINT_ASSERT(AST, rhs_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(rhs_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs_, program_id);
TINT_ASSERT(op_ != BinaryOp::kNone); TINT_ASSERT(AST, op_ != BinaryOp::kNone);
} }
BinaryExpression::BinaryExpression(BinaryExpression&&) = default; BinaryExpression::BinaryExpression(BinaryExpression&&) = default;

View File

@ -26,9 +26,9 @@ BitcastExpression::BitcastExpression(ProgramID program_id,
ast::Type* type, ast::Type* type,
Expression* expr) Expression* expr)
: Base(program_id, source), type_(type), expr_(expr) { : Base(program_id, source), type_(type), expr_(expr) {
TINT_ASSERT(type_); TINT_ASSERT(AST, type_);
TINT_ASSERT(expr_); TINT_ASSERT(AST, expr_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(expr, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
} }
BitcastExpression::BitcastExpression(BitcastExpression&&) = default; BitcastExpression::BitcastExpression(BitcastExpression&&) = default;

View File

@ -26,8 +26,8 @@ BlockStatement::BlockStatement(ProgramID program_id,
const StatementList& statements) const StatementList& statements)
: Base(program_id, source), statements_(std::move(statements)) { : Base(program_id, source), statements_(std::move(statements)) {
for (auto* stmt : *this) { for (auto* stmt : *this) {
TINT_ASSERT(stmt); TINT_ASSERT(AST, stmt);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(stmt, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
} }
} }

View File

@ -26,11 +26,11 @@ CallExpression::CallExpression(ProgramID program_id,
IdentifierExpression* func, IdentifierExpression* func,
ExpressionList params) ExpressionList params)
: Base(program_id, source), func_(func), params_(params) { : Base(program_id, source), func_(func), params_(params) {
TINT_ASSERT(func_); TINT_ASSERT(AST, func_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(func_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func_, program_id);
for (auto* param : params_) { for (auto* param : params_) {
TINT_ASSERT(param); TINT_ASSERT(AST, param);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(param, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, param, program_id);
} }
} }

View File

@ -25,8 +25,8 @@ CallStatement::CallStatement(ProgramID program_id,
const Source& source, const Source& source,
CallExpression* call) CallExpression* call)
: Base(program_id, source), call_(call) { : Base(program_id, source), call_(call) {
TINT_ASSERT(call_); TINT_ASSERT(AST, call_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(call_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, call_, program_id);
} }
CallStatement::CallStatement(CallStatement&&) = default; CallStatement::CallStatement(CallStatement&&) = default;

View File

@ -26,11 +26,11 @@ CaseStatement::CaseStatement(ProgramID program_id,
CaseSelectorList selectors, CaseSelectorList selectors,
BlockStatement* body) BlockStatement* body)
: Base(program_id, source), selectors_(selectors), body_(body) { : Base(program_id, source), selectors_(selectors), body_(body) {
TINT_ASSERT(body_); TINT_ASSERT(AST, body_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(body_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
for (auto* selector : selectors) { for (auto* selector : selectors) {
TINT_ASSERT(selector); TINT_ASSERT(AST, selector);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(selector, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, selector, program_id);
} }
} }

View File

@ -33,7 +33,7 @@ DepthTexture::DepthTexture(ProgramID program_id,
const Source& source, const Source& source,
TextureDimension dim) TextureDimension dim)
: Base(program_id, source, dim) { : Base(program_id, source, dim) {
TINT_ASSERT(IsValidDepthDimension(dim)); TINT_ASSERT(AST, IsValidDepthDimension(dim));
} }
DepthTexture::DepthTexture(DepthTexture&&) = default; DepthTexture::DepthTexture(DepthTexture&&) = default;

View File

@ -26,9 +26,9 @@ ElseStatement::ElseStatement(ProgramID program_id,
Expression* condition, Expression* condition,
BlockStatement* body) BlockStatement* body)
: Base(program_id, source), condition_(condition), body_(body) { : Base(program_id, source), condition_(condition), body_(body) {
TINT_ASSERT(body_); TINT_ASSERT(AST, body_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(body_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(condition_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
} }
ElseStatement::ElseStatement(ElseStatement&&) = default; ElseStatement::ElseStatement(ElseStatement&&) = default;

View File

@ -38,19 +38,19 @@ Function::Function(ProgramID program_id,
body_(body), body_(body),
decorations_(std::move(decorations)), decorations_(std::move(decorations)),
return_type_decorations_(std::move(return_type_decorations)) { return_type_decorations_(std::move(return_type_decorations)) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(symbol_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(body, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
for (auto* param : params_) { for (auto* param : params_) {
TINT_ASSERT(param && param->is_const()); TINT_ASSERT(AST, param && param->is_const());
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(param, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, param, program_id);
} }
TINT_ASSERT(symbol_.IsValid()); TINT_ASSERT(AST, symbol_.IsValid());
TINT_ASSERT(return_type_); TINT_ASSERT(AST, return_type_);
for (auto* deco : decorations_) { for (auto* deco : decorations_) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(deco, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
} }
for (auto* deco : return_type_decorations_) { for (auto* deco : return_type_decorations_) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(deco, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
} }
} }

View File

@ -25,8 +25,8 @@ IdentifierExpression::IdentifierExpression(ProgramID program_id,
const Source& source, const Source& source,
Symbol sym) Symbol sym)
: Base(program_id, source), sym_(sym) { : Base(program_id, source), sym_(sym) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(sym_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, sym_, program_id);
TINT_ASSERT(sym_.IsValid()); TINT_ASSERT(AST, sym_.IsValid());
} }
IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default; IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default;

View File

@ -30,13 +30,13 @@ IfStatement::IfStatement(ProgramID program_id,
condition_(condition), condition_(condition),
body_(body), body_(body),
else_statements_(std::move(else_stmts)) { else_statements_(std::move(else_stmts)) {
TINT_ASSERT(condition_); TINT_ASSERT(AST, condition_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(condition_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
TINT_ASSERT(body_); TINT_ASSERT(AST, body_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(body_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
for (auto* el : else_statements_) { for (auto* el : else_statements_) {
TINT_ASSERT(el); TINT_ASSERT(AST, el);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(el, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, el, program_id);
} }
} }

View File

@ -142,7 +142,7 @@ ast::Type* TextureOverloadCase::buildResultVectorComponentType(
return b->ty.i32(); return b->ty.i32();
} }
TINT_UNREACHABLE(b->Diagnostics()); TINT_UNREACHABLE(AST, b->Diagnostics());
return {}; return {};
} }
@ -176,7 +176,7 @@ ast::Variable* TextureOverloadCase::buildTextureVariable(
} }
} }
TINT_UNREACHABLE(b->Diagnostics()); TINT_UNREACHABLE(AST, b->Diagnostics());
return nullptr; return nullptr;
} }

View File

@ -26,9 +26,9 @@ LoopStatement::LoopStatement(ProgramID program_id,
BlockStatement* body, BlockStatement* body,
BlockStatement* continuing) BlockStatement* continuing)
: Base(program_id, source), body_(body), continuing_(continuing) { : Base(program_id, source), body_(body), continuing_(continuing) {
TINT_ASSERT(body_); TINT_ASSERT(AST, body_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(body_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(continuing_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing_, program_id);
} }
LoopStatement::LoopStatement(LoopStatement&&) = default; LoopStatement::LoopStatement(LoopStatement&&) = default;

View File

@ -30,10 +30,10 @@ Matrix::Matrix(ProgramID program_id,
subtype_(subtype), subtype_(subtype),
rows_(rows), rows_(rows),
columns_(columns) { columns_(columns) {
TINT_ASSERT(rows > 1); TINT_ASSERT(AST, rows > 1);
TINT_ASSERT(rows < 5); TINT_ASSERT(AST, rows < 5);
TINT_ASSERT(columns > 1); TINT_ASSERT(AST, columns > 1);
TINT_ASSERT(columns < 5); TINT_ASSERT(AST, columns < 5);
} }
Matrix::Matrix(Matrix&&) = default; Matrix::Matrix(Matrix&&) = default;

View File

@ -26,10 +26,10 @@ MemberAccessorExpression::MemberAccessorExpression(ProgramID program_id,
Expression* structure, Expression* structure,
IdentifierExpression* member) IdentifierExpression* member)
: Base(program_id, source), struct_(structure), member_(member) { : Base(program_id, source), struct_(structure), member_(member) {
TINT_ASSERT(struct_); TINT_ASSERT(AST, struct_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(struct_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, struct_, program_id);
TINT_ASSERT(member_); TINT_ASSERT(AST, member_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(member_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, member_, program_id);
} }
MemberAccessorExpression::MemberAccessorExpression(MemberAccessorExpression&&) = MemberAccessorExpression::MemberAccessorExpression(MemberAccessorExpression&&) =

View File

@ -44,7 +44,7 @@ Module::Module(ProgramID program_id,
global_variables_.push_back(var); global_variables_.push_back(var);
} else { } else {
diag::List diagnostics; diag::List diagnostics;
TINT_ICE(diagnostics) << "Unknown global declaration type"; TINT_ICE(AST, diagnostics) << "Unknown global declaration type";
} }
} }
} }
@ -61,22 +61,22 @@ const ast::TypeDecl* Module::LookupType(Symbol name) const {
} }
void Module::AddGlobalVariable(ast::Variable* var) { void Module::AddGlobalVariable(ast::Variable* var) {
TINT_ASSERT(var); TINT_ASSERT(AST, var);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(var, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id());
global_variables_.push_back(var); global_variables_.push_back(var);
global_declarations_.push_back(var); global_declarations_.push_back(var);
} }
void Module::AddTypeDecl(ast::TypeDecl* type) { void Module::AddTypeDecl(ast::TypeDecl* type) {
TINT_ASSERT(type); TINT_ASSERT(AST, type);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(type, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id());
type_decls_.push_back(type); type_decls_.push_back(type);
global_declarations_.push_back(type); global_declarations_.push_back(type);
} }
void Module::AddFunction(ast::Function* func) { void Module::AddFunction(ast::Function* func) {
TINT_ASSERT(func); TINT_ASSERT(AST, func);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(func, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id());
functions_.push_back(func); functions_.push_back(func);
global_declarations_.push_back(func); global_declarations_.push_back(func);
} }
@ -98,20 +98,22 @@ void Module::Copy(CloneContext* ctx, const Module* src) {
for (auto* decl : global_declarations_) { for (auto* decl : global_declarations_) {
if (!decl) { if (!decl) {
TINT_ICE(ctx->dst->Diagnostics()) << "src global declaration was nullptr"; TINT_ICE(AST, ctx->dst->Diagnostics())
<< "src global declaration was nullptr";
continue; continue;
} }
if (auto* type = decl->As<ast::TypeDecl>()) { if (auto* type = decl->As<ast::TypeDecl>()) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(type, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id());
type_decls_.push_back(type); type_decls_.push_back(type);
} else if (auto* func = decl->As<Function>()) { } else if (auto* func = decl->As<Function>()) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(func, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id());
functions_.push_back(func); functions_.push_back(func);
} else if (auto* var = decl->As<Variable>()) { } else if (auto* var = decl->As<Variable>()) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(var, program_id()); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id());
global_variables_.push_back(var); global_variables_.push_back(var);
} else { } else {
TINT_ICE(ctx->dst->Diagnostics()) << "Unknown global declaration type"; TINT_ICE(AST, ctx->dst->Diagnostics())
<< "Unknown global declaration type";
} }
} }
} }

View File

@ -26,7 +26,7 @@ MultisampledTexture::MultisampledTexture(ProgramID program_id,
TextureDimension dim, TextureDimension dim,
Type* type) Type* type)
: Base(program_id, source, dim), type_(type) { : Base(program_id, source, dim), type_(type) {
TINT_ASSERT(type_); TINT_ASSERT(AST, type_);
} }
MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default; MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default;

View File

@ -28,7 +28,7 @@ ReturnStatement::ReturnStatement(ProgramID program_id,
const Source& source, const Source& source,
Expression* value) Expression* value)
: Base(program_id, source), value_(value) { : Base(program_id, source), value_(value) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(value_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, value_, program_id);
} }
ReturnStatement::ReturnStatement(ReturnStatement&&) = default; ReturnStatement::ReturnStatement(ReturnStatement&&) = default;

View File

@ -26,7 +26,7 @@ SampledTexture::SampledTexture(ProgramID program_id,
TextureDimension dim, TextureDimension dim,
Type const* type) Type const* type)
: Base(program_id, source, dim), type_(type) { : Base(program_id, source, dim), type_(type) {
TINT_ASSERT(type_); TINT_ASSERT(AST, type_);
} }
SampledTexture::SampledTexture(SampledTexture&&) = default; SampledTexture::SampledTexture(SampledTexture&&) = default;

View File

@ -25,8 +25,8 @@ ScalarConstructorExpression::ScalarConstructorExpression(ProgramID program_id,
const Source& source, const Source& source,
Literal* literal) Literal* literal)
: Base(program_id, source), literal_(literal) { : Base(program_id, source), literal_(literal) {
TINT_ASSERT(literal); TINT_ASSERT(AST, literal);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(literal, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, literal, program_id);
} }
ScalarConstructorExpression::ScalarConstructorExpression( ScalarConstructorExpression::ScalarConstructorExpression(

View File

@ -33,12 +33,12 @@ Struct::Struct(ProgramID program_id,
members_(std::move(members)), members_(std::move(members)),
decorations_(std::move(decorations)) { decorations_(std::move(decorations)) {
for (auto* mem : members_) { for (auto* mem : members_) {
TINT_ASSERT(mem); TINT_ASSERT(AST, mem);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(mem, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, mem, program_id);
} }
for (auto* deco : decorations_) { for (auto* deco : decorations_) {
TINT_ASSERT(deco); TINT_ASSERT(AST, deco);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(deco, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
} }
} }

View File

@ -30,12 +30,12 @@ StructMember::StructMember(ProgramID program_id,
symbol_(sym), symbol_(sym),
type_(type), type_(type),
decorations_(std::move(decorations)) { decorations_(std::move(decorations)) {
TINT_ASSERT(type); TINT_ASSERT(AST, type);
TINT_ASSERT(symbol_.IsValid()); TINT_ASSERT(AST, symbol_.IsValid());
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(symbol_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
for (auto* deco : decorations_) { for (auto* deco : decorations_) {
TINT_ASSERT(deco); TINT_ASSERT(AST, deco);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(deco, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
} }
} }

View File

@ -26,11 +26,11 @@ SwitchStatement::SwitchStatement(ProgramID program_id,
Expression* condition, Expression* condition,
CaseStatementList body) CaseStatementList body)
: Base(program_id, source), condition_(condition), body_(body) { : Base(program_id, source), condition_(condition), body_(body) {
TINT_ASSERT(condition_); TINT_ASSERT(AST, condition_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(condition_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
for (auto* stmt : body_) { for (auto* stmt : body_) {
TINT_ASSERT(stmt); TINT_ASSERT(AST, stmt);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(stmt, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
} }
} }

View File

@ -26,10 +26,10 @@ TypeConstructorExpression::TypeConstructorExpression(ProgramID program_id,
ast::Type* type, ast::Type* type,
ExpressionList values) ExpressionList values)
: Base(program_id, source), type_(type), values_(std::move(values)) { : Base(program_id, source), type_(type), values_(std::move(values)) {
TINT_ASSERT(type_); TINT_ASSERT(AST, type_);
for (auto* val : values_) { for (auto* val : values_) {
TINT_ASSERT(val); TINT_ASSERT(AST, val);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(val, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, val, program_id);
} }
} }

View File

@ -23,7 +23,7 @@ namespace ast {
TypeDecl::TypeDecl(ProgramID program_id, const Source& source, Symbol name) TypeDecl::TypeDecl(ProgramID program_id, const Source& source, Symbol name)
: Base(program_id, source), name_(name) { : Base(program_id, source), name_(name) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(name, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
} }
TypeDecl::TypeDecl(TypeDecl&&) = default; TypeDecl::TypeDecl(TypeDecl&&) = default;

View File

@ -26,8 +26,8 @@ UnaryOpExpression::UnaryOpExpression(ProgramID program_id,
UnaryOp op, UnaryOp op,
Expression* expr) Expression* expr)
: Base(program_id, source), op_(op), expr_(expr) { : Base(program_id, source), op_(op), expr_(expr) {
TINT_ASSERT(expr_); TINT_ASSERT(AST, expr_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(expr_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr_, program_id);
} }
UnaryOpExpression::UnaryOpExpression(UnaryOpExpression&&) = default; UnaryOpExpression::UnaryOpExpression(UnaryOpExpression&&) = default;

View File

@ -40,9 +40,9 @@ Variable::Variable(ProgramID program_id,
decorations_(std::move(decorations)), decorations_(std::move(decorations)),
declared_storage_class_(declared_storage_class), declared_storage_class_(declared_storage_class),
declared_access_(declared_access) { declared_access_(declared_access) {
TINT_ASSERT(symbol_.IsValid()); TINT_ASSERT(AST, symbol_.IsValid());
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(symbol_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(constructor, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, constructor, program_id);
} }
Variable::Variable(Variable&&) = default; Variable::Variable(Variable&&) = default;

View File

@ -25,8 +25,8 @@ VariableDeclStatement::VariableDeclStatement(ProgramID program_id,
const Source& source, const Source& source,
Variable* variable) Variable* variable)
: Base(program_id, source), variable_(variable) { : Base(program_id, source), variable_(variable) {
TINT_ASSERT(variable_); TINT_ASSERT(AST, variable_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(variable_, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, variable_, program_id);
} }
VariableDeclStatement::VariableDeclStatement(VariableDeclStatement&&) = default; VariableDeclStatement::VariableDeclStatement(VariableDeclStatement&&) = default;

View File

@ -26,8 +26,8 @@ Vector::Vector(ProgramID program_id,
Type const* subtype, Type const* subtype,
uint32_t size) uint32_t size)
: Base(program_id, source), subtype_(subtype), size_(size) { : Base(program_id, source), subtype_(subtype), size_(size) {
TINT_ASSERT(size_ > 1); TINT_ASSERT(AST, size_ > 1);
TINT_ASSERT(size_ < 5); TINT_ASSERT(AST, size_ < 5);
} }
Vector::Vector(Vector&&) = default; Vector::Vector(Vector&&) = default;

View File

@ -105,7 +105,7 @@ class CloneContext {
} }
if (src) { if (src) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, a);
} }
// Was Replace() called for this object? // Was Replace() called for this object?
@ -134,7 +134,7 @@ class CloneContext {
auto* out = CheckedCast<T>(cloned); auto* out = CheckedCast<T>(cloned);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, out); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, out);
return out; return out;
} }
@ -160,7 +160,7 @@ class CloneContext {
} }
if (src) { if (src) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, a);
} }
// Have we seen this object before? If so, return the previously cloned // Have we seen this object before? If so, return the previously cloned
@ -323,7 +323,7 @@ class CloneContext {
for (auto& transform : transforms_) { for (auto& transform : transforms_) {
if (transform.typeinfo->Is(TypeInfo::Of<T>()) || if (transform.typeinfo->Is(TypeInfo::Of<T>()) ||
TypeInfo::Of<T>().Is(*transform.typeinfo)) { TypeInfo::Of<T>().Is(*transform.typeinfo)) {
TINT_ICE(Diagnostics()) TINT_ICE(Clone, Diagnostics())
<< "ReplaceAll() called with a handler for type " << "ReplaceAll() called with a handler for type "
<< TypeInfo::Of<T>().name << TypeInfo::Of<T>().name
<< " that is already handled by a handler for type " << " that is already handled by a handler for type "
@ -349,8 +349,9 @@ class CloneContext {
/// @returns this CloneContext so calls can be chained /// @returns this CloneContext so calls can be chained
CloneContext& ReplaceAll(const SymbolTransform& replacer) { CloneContext& ReplaceAll(const SymbolTransform& replacer) {
if (symbol_transform_) { if (symbol_transform_) {
TINT_ICE(Diagnostics()) << "ReplaceAll(const SymbolTransform&) called " TINT_ICE(Clone, Diagnostics())
"multiple times on the same CloneContext"; << "ReplaceAll(const SymbolTransform&) called "
"multiple times on the same CloneContext";
return *this; return *this;
} }
symbol_transform_ = replacer; symbol_transform_ = replacer;
@ -369,8 +370,8 @@ class CloneContext {
/// @returns this CloneContext so calls can be chained /// @returns this CloneContext so calls can be chained
template <typename WHAT, typename WITH> template <typename WHAT, typename WITH>
CloneContext& Replace(WHAT* what, WITH* with) { CloneContext& Replace(WHAT* what, WITH* with) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, what); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, what);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, with); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, with);
replacements_[what] = with; replacements_[what] = with;
return *this; return *this;
} }
@ -382,9 +383,9 @@ class CloneContext {
/// @returns this CloneContext so calls can be chained /// @returns this CloneContext so calls can be chained
template <typename T, typename OBJECT> template <typename T, typename OBJECT>
CloneContext& Remove(const std::vector<T>& vector, OBJECT* object) { CloneContext& Remove(const std::vector<T>& vector, OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, object); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object);
if (std::find(vector.begin(), vector.end(), object) == vector.end()) { if (std::find(vector.begin(), vector.end(), object) == vector.end()) {
TINT_ICE(Diagnostics()) TINT_ICE(Clone, Diagnostics())
<< "CloneContext::Remove() vector does not contain object"; << "CloneContext::Remove() vector does not contain object";
return *this; return *this;
} }
@ -400,7 +401,7 @@ class CloneContext {
/// @returns this CloneContext so calls can be chained /// @returns this CloneContext so calls can be chained
template <typename T, typename OBJECT> template <typename T, typename OBJECT>
CloneContext& InsertFront(const std::vector<T>& vector, OBJECT* object) { CloneContext& InsertFront(const std::vector<T>& vector, OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, object); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
auto& transforms = list_transforms_[&vector]; auto& transforms = list_transforms_[&vector];
auto& list = transforms.insert_front_; auto& list = transforms.insert_front_;
list.emplace_back(object); list.emplace_back(object);
@ -414,7 +415,7 @@ class CloneContext {
/// @returns this CloneContext so calls can be chained /// @returns this CloneContext so calls can be chained
template <typename T, typename OBJECT> template <typename T, typename OBJECT>
CloneContext& InsertBack(const std::vector<T>& vector, OBJECT* object) { CloneContext& InsertBack(const std::vector<T>& vector, OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, object); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
auto& transforms = list_transforms_[&vector]; auto& transforms = list_transforms_[&vector];
auto& list = transforms.insert_back_; auto& list = transforms.insert_back_;
list.emplace_back(object); list.emplace_back(object);
@ -431,10 +432,10 @@ class CloneContext {
CloneContext& InsertBefore(const std::vector<T>& vector, CloneContext& InsertBefore(const std::vector<T>& vector,
const BEFORE* before, const BEFORE* before,
OBJECT* object) { OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, before); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, before);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, object); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
if (std::find(vector.begin(), vector.end(), before) == vector.end()) { if (std::find(vector.begin(), vector.end(), before) == vector.end()) {
TINT_ICE(Diagnostics()) TINT_ICE(Clone, Diagnostics())
<< "CloneContext::InsertBefore() vector does not contain before"; << "CloneContext::InsertBefore() vector does not contain before";
return *this; return *this;
} }
@ -455,10 +456,10 @@ class CloneContext {
CloneContext& InsertAfter(const std::vector<T>& vector, CloneContext& InsertAfter(const std::vector<T>& vector,
const AFTER* after, const AFTER* after,
OBJECT* object) { OBJECT* object) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, after); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, after);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, object); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object);
if (std::find(vector.begin(), vector.end(), after) == vector.end()) { if (std::find(vector.begin(), vector.end(), after) == vector.end()) {
TINT_ICE(Diagnostics()) TINT_ICE(Clone, Diagnostics())
<< "CloneContext::InsertAfter() vector does not contain after"; << "CloneContext::InsertAfter() vector does not contain after";
return *this; return *this;
} }
@ -505,7 +506,7 @@ class CloneContext {
if (TO* cast = As<TO>(obj)) { if (TO* cast = As<TO>(obj)) {
return cast; return cast;
} }
TINT_ICE(Diagnostics()) TINT_ICE(Clone, Diagnostics())
<< "Cloned object was not of the expected type\n" << "Cloned object was not of the expected type\n"
<< "got: " << (obj ? obj->TypeInfo().name : "<null>") << "\n" << "got: " << (obj ? obj->TypeInfo().name : "<null>") << "\n"
<< "expected: " << TypeInfo::Of<TO>().name; << "expected: " << TypeInfo::Of<TO>().name;

View File

@ -783,7 +783,7 @@ TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedBySrc) {
Allocator allocator; Allocator allocator;
ctx.Clone(allocator.Create<ProgramNode>(ProgramID::New(), dst.ID())); ctx.Clone(allocator.Create<ProgramNode>(ProgramID::New(), dst.ID()));
}, },
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(src, a))"); R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, a))");
} }
TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedByDst) { TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedByDst) {
@ -795,7 +795,7 @@ TEST_F(CloneContextTest, ProgramIDs_Clone_ObjectNotOwnedByDst) {
Allocator allocator; Allocator allocator;
ctx.Clone(allocator.Create<ProgramNode>(src.ID(), ProgramID::New())); ctx.Clone(allocator.Create<ProgramNode>(src.ID(), ProgramID::New()));
}, },
R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(dst, out))"); R"(internal compiler error: TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, out))");
} }
} // namespace } // namespace

View File

@ -27,12 +27,13 @@ void SetInternalCompilerErrorReporter(InternalCompilerErrorReporter* reporter) {
InternalCompilerError::InternalCompilerError(const char* file, InternalCompilerError::InternalCompilerError(const char* file,
size_t line, size_t line,
diag::System system,
diag::List& diagnostics) diag::List& diagnostics)
: file_(file), line_(line), diagnostics_(diagnostics) {} : file_(file), line_(line), system_(system), diagnostics_(diagnostics) {}
InternalCompilerError::~InternalCompilerError() { InternalCompilerError::~InternalCompilerError() {
Source source{Source::Range{Source::Location{line_}}, file_}; Source source{Source::Range{Source::Location{line_}}, file_};
diagnostics_.add_ice(msg_.str(), source); diagnostics_.add_ice(system_, msg_.str(), source);
if (ice_reporter) { if (ice_reporter) {
ice_reporter(diagnostics_); ice_reporter(diagnostics_);

View File

@ -44,8 +44,12 @@ class InternalCompilerError {
/// Constructor /// Constructor
/// @param file the file containing the ICE /// @param file the file containing the ICE
/// @param line the line containing the ICE /// @param line the line containing the ICE
/// @param system the Tint system that has raised the ICE
/// @param diagnostics the list of diagnostics to append the ICE message to /// @param diagnostics the list of diagnostics to append the ICE message to
InternalCompilerError(const char* file, size_t line, diag::List& diagnostics); InternalCompilerError(const char* file,
size_t line,
diag::System system,
diag::List& diagnostics);
/// Destructor. /// Destructor.
/// Adds the internal compiler error message to the diagnostics list, and then /// Adds the internal compiler error message to the diagnostics list, and then
@ -64,6 +68,7 @@ class InternalCompilerError {
private: private:
char const* const file_; char const* const file_;
size_t const line_; size_t const line_;
diag::System system_;
diag::List& diagnostics_; diag::List& diagnostics_;
std::stringstream msg_; std::stringstream msg_;
}; };
@ -76,8 +81,9 @@ class InternalCompilerError {
/// set. /// set.
/// The ICE message contains the callsite's file and line. /// The ICE message contains the callsite's file and line.
/// Use the `<<` operator to append an error message to the ICE. /// Use the `<<` operator to append an error message to the ICE.
#define TINT_ICE(diagnostics) \ #define TINT_ICE(system, diagnostics) \
tint::InternalCompilerError(__FILE__, __LINE__, diagnostics) tint::InternalCompilerError(__FILE__, __LINE__, \
::tint::diag::System::system, diagnostics)
/// TINT_UNREACHABLE() is a macro for appending a "TINT_UNREACHABLE" /// TINT_UNREACHABLE() is a macro for appending a "TINT_UNREACHABLE"
/// internal compiler error message to the diagnostics list `diagnostics`, and /// internal compiler error message to the diagnostics list `diagnostics`, and
@ -85,8 +91,8 @@ class InternalCompilerError {
/// reporter is set. /// reporter is set.
/// The ICE message contains the callsite's file and line. /// The ICE message contains the callsite's file and line.
/// Use the `<<` operator to append an error message to the ICE. /// Use the `<<` operator to append an error message to the ICE.
#define TINT_UNREACHABLE(diagnostics) \ #define TINT_UNREACHABLE(system, diagnostics) \
TINT_ICE(diagnostics) << "TINT_UNREACHABLE " TINT_ICE(system, diagnostics) << "TINT_UNREACHABLE "
/// TINT_UNIMPLEMENTED() is a macro for appending a "TINT_UNIMPLEMENTED" /// TINT_UNIMPLEMENTED() is a macro for appending a "TINT_UNIMPLEMENTED"
/// internal compiler error message to the diagnostics list `diagnostics`, and /// internal compiler error message to the diagnostics list `diagnostics`, and
@ -94,8 +100,8 @@ class InternalCompilerError {
/// reporter is set. /// reporter is set.
/// The ICE message contains the callsite's file and line. /// The ICE message contains the callsite's file and line.
/// Use the `<<` operator to append an error message to the ICE. /// Use the `<<` operator to append an error message to the ICE.
#define TINT_UNIMPLEMENTED(diagnostics) \ #define TINT_UNIMPLEMENTED(system, diagnostics) \
TINT_ICE(diagnostics) << "TINT_UNIMPLEMENTED " TINT_ICE(system, diagnostics) << "TINT_UNIMPLEMENTED "
/// TINT_ASSERT() is a macro for checking the expression is true, triggering a /// TINT_ASSERT() is a macro for checking the expression is true, triggering a
/// TINT_ICE if it is not. /// TINT_ICE if it is not.
@ -105,12 +111,12 @@ class InternalCompilerError {
/// may silently fail in builds where SetInternalCompilerErrorReporter() is not /// may silently fail in builds where SetInternalCompilerErrorReporter() is not
/// called. Only use in places where there's no sensible place to put proper /// called. Only use in places where there's no sensible place to put proper
/// error handling. /// error handling.
#define TINT_ASSERT(condition) \ #define TINT_ASSERT(system, condition) \
do { \ do { \
if (!(condition)) { \ if (!(condition)) { \
tint::diag::List diagnostics; \ tint::diag::List diagnostics; \
TINT_ICE(diagnostics) << "TINT_ASSERT(" << #condition << ")"; \ TINT_ICE(system, diagnostics) << "TINT_ASSERT(" << #condition << ")"; \
} \ } \
} while (false) } while (false)
#endif // SRC_DEBUG_H_ #endif // SRC_DEBUG_H_

View File

@ -23,17 +23,18 @@ TEST(DebugTest, Unreachable) {
EXPECT_FATAL_FAILURE( EXPECT_FATAL_FAILURE(
{ {
diag::List diagnostics; diag::List diagnostics;
TINT_UNREACHABLE(diagnostics); TINT_UNREACHABLE(Test, diagnostics);
}, },
"internal compiler error"); "internal compiler error");
} }
TEST(DebugTest, AssertTrue) { TEST(DebugTest, AssertTrue) {
TINT_ASSERT(true); TINT_ASSERT(Test, true);
} }
TEST(DebugTest, AssertFalse) { TEST(DebugTest, AssertFalse) {
EXPECT_FATAL_FAILURE({ TINT_ASSERT(false); }, "internal compiler error"); EXPECT_FATAL_FAILURE({ TINT_ASSERT(Test, false); },
"internal compiler error");
} }
} // namespace } // namespace

View File

@ -32,6 +32,24 @@ inline bool operator>=(Severity a, Severity b) {
return static_cast<int>(a) >= static_cast<int>(b); return static_cast<int>(a) >= static_cast<int>(b);
} }
/// System is an enumerator of Tint systems that can be the originator of a
/// diagnostic message.
enum class System {
AST,
Clone,
Inspector,
Program,
ProgramBuilder,
Reader,
Resolver,
Semantic,
Symbol,
Test,
Transform,
Utils,
Writer,
};
/// Diagnostic holds all the information for a single compiler diagnostic /// Diagnostic holds all the information for a single compiler diagnostic
/// message. /// message.
class Diagnostic { class Diagnostic {
@ -42,6 +60,8 @@ class Diagnostic {
Source source; Source source;
/// message is the text associated with the diagnostic. /// message is the text associated with the diagnostic.
std::string message; std::string message;
/// system is the Tint system that raised the diagnostic.
System system;
/// code is the error code, for example a validation error might have the code /// code is the error code, for example a validation error might have the code
/// `"v-0001"`. /// `"v-0001"`.
const char* code = nullptr; const char* code = nullptr;
@ -98,42 +118,54 @@ class List {
} }
/// adds the note message with the given Source to the end of this list. /// adds the note message with the given Source to the end of this list.
/// @param system the system raising the note message
/// @param note_msg the note message /// @param note_msg the note message
/// @param source the source of the note diagnostic /// @param source the source of the note diagnostic
void add_note(const std::string& note_msg, const Source& source) { void add_note(System system,
diag::Diagnostic error{}; const std::string& note_msg,
error.severity = diag::Severity::Note; const Source& source) {
error.source = source; diag::Diagnostic note{};
error.message = note_msg; note.severity = diag::Severity::Note;
add(std::move(error)); note.system = system;
note.source = source;
note.message = note_msg;
add(std::move(note));
} }
/// adds the warning message with the given Source to the end of this list. /// adds the warning message with the given Source to the end of this list.
/// @param system the system raising the warning message
/// @param warning_msg the warning message /// @param warning_msg the warning message
/// @param source the source of the warning diagnostic /// @param source the source of the warning diagnostic
void add_warning(const std::string& warning_msg, const Source& source) { void add_warning(System system,
diag::Diagnostic error{}; const std::string& warning_msg,
error.severity = diag::Severity::Warning; const Source& source) {
error.source = source; diag::Diagnostic warning{};
error.message = warning_msg; warning.severity = diag::Severity::Warning;
add(std::move(error)); warning.system = system;
warning.source = source;
warning.message = warning_msg;
add(std::move(warning));
} }
/// adds the error message without a source to the end of this list. /// adds the error message without a source to the end of this list.
/// @param system the system raising the error message
/// @param err_msg the error message /// @param err_msg the error message
void add_error(std::string err_msg) { void add_error(System system, std::string err_msg) {
diag::Diagnostic error{}; diag::Diagnostic error{};
error.severity = diag::Severity::Error; error.severity = diag::Severity::Error;
error.system = system;
error.message = std::move(err_msg); error.message = std::move(err_msg);
add(std::move(error)); add(std::move(error));
} }
/// adds the error message with the given Source to the end of this list. /// adds the error message with the given Source to the end of this list.
/// @param system the system raising the error message
/// @param err_msg the error message /// @param err_msg the error message
/// @param source the source of the error diagnostic /// @param source the source of the error diagnostic
void add_error(std::string err_msg, const Source& source) { void add_error(System system, std::string err_msg, const Source& source) {
diag::Diagnostic error{}; diag::Diagnostic error{};
error.severity = diag::Severity::Error; error.severity = diag::Severity::Error;
error.system = system;
error.source = source; error.source = source;
error.message = std::move(err_msg); error.message = std::move(err_msg);
add(std::move(error)); add(std::move(error));
@ -141,24 +173,33 @@ class List {
/// adds the error message with the given code and Source to the end of this /// adds the error message with the given code and Source to the end of this
/// list. /// list.
/// @param system the system raising the error message
/// @param code the error code /// @param code the error code
/// @param err_msg the error message /// @param err_msg the error message
/// @param source the source of the error diagnostic /// @param source the source of the error diagnostic
void add_error(const char* code, std::string err_msg, const Source& source) { void add_error(System system,
const char* code,
std::string err_msg,
const Source& source) {
diag::Diagnostic error{}; diag::Diagnostic error{};
error.code = code; error.code = code;
error.severity = diag::Severity::Error; error.severity = diag::Severity::Error;
error.system = system;
error.source = source; error.source = source;
error.message = std::move(err_msg); error.message = std::move(err_msg);
add(std::move(error)); add(std::move(error));
} }
/// adds an internal compiler error message to the end of this list. /// adds an internal compiler error message to the end of this list.
/// @param system the system raising the error message
/// @param err_msg the error message /// @param err_msg the error message
/// @param source the source of the internal compiler error /// @param source the source of the internal compiler error
void add_ice(const std::string& err_msg, const Source& source) { void add_ice(System system,
const std::string& err_msg,
const Source& source) {
diag::Diagnostic ice{}; diag::Diagnostic ice{};
ice.severity = diag::Severity::InternalCompilerError; ice.severity = diag::Severity::InternalCompilerError;
ice.system = system;
ice.source = source; ice.source = source;
ice.message = err_msg; ice.message = err_msg;
add(std::move(ice)); add(std::move(ice));

View File

@ -33,18 +33,19 @@ class DiagFormatterTest : public testing::Test {
Source::File file{"file.name", content}; Source::File file{"file.name", content};
Diagnostic diag_note{Severity::Note, Diagnostic diag_note{Severity::Note,
Source{Source::Range{Source::Location{1, 14}}, &file}, Source{Source::Range{Source::Location{1, 14}}, &file},
"purr"}; "purr", System::Test};
Diagnostic diag_warn{Severity::Warning, Diagnostic diag_warn{Severity::Warning,
Source{Source::Range{{2, 14}, {2, 18}}, &file}, "grrr"}; Source{Source::Range{{2, 14}, {2, 18}}, &file}, "grrr",
System::Test};
Diagnostic diag_err{Severity::Error, Diagnostic diag_err{Severity::Error,
Source{Source::Range{{3, 16}, {3, 21}}, &file}, "hiss", Source{Source::Range{{3, 16}, {3, 21}}, &file}, "hiss",
"abc123"}; System::Test, "abc123"};
Diagnostic diag_ice{Severity::InternalCompilerError, Diagnostic diag_ice{Severity::InternalCompilerError,
Source{Source::Range{{4, 16}, {4, 19}}, &file}, Source{Source::Range{{4, 16}, {4, 19}}, &file},
"unreachable"}; "unreachable", System::Test};
Diagnostic diag_fatal{Severity::Fatal, Diagnostic diag_fatal{Severity::Fatal,
Source{Source::Range{{4, 16}, {4, 19}}, &file}, Source{Source::Range{{4, 16}, {4, 19}}, &file},
"nothing"}; "nothing", System::Test};
}; };
TEST_F(DiagFormatterTest, Simple) { TEST_F(DiagFormatterTest, Simple) {
@ -68,7 +69,7 @@ TEST_F(DiagFormatterTest, SimpleNewlineAtEnd) {
TEST_F(DiagFormatterTest, SimpleNoSource) { TEST_F(DiagFormatterTest, SimpleNoSource) {
Formatter fmt{{false, false, false, false}}; Formatter fmt{{false, false, false, false}};
Diagnostic diag{Severity::Note, Source{}, "no source!"}; Diagnostic diag{Severity::Note, Source{}, "no source!", System::Test};
auto got = fmt.format(List{diag}); auto got = fmt.format(List{diag});
auto* expect = "no source!"; auto* expect = "no source!";
ASSERT_EQ(expect, got); ASSERT_EQ(expect, got);
@ -131,7 +132,7 @@ the snake says quack
TEST_F(DiagFormatterTest, BasicWithMultiLine) { TEST_F(DiagFormatterTest, BasicWithMultiLine) {
Diagnostic multiline{Severity::Warning, Diagnostic multiline{Severity::Warning,
Source{Source::Range{{2, 9}, {4, 15}}, &file}, Source{Source::Range{{2, 9}, {4, 15}}, &file},
"multiline"}; "multiline", System::Test};
Formatter fmt{{false, false, true, false}}; Formatter fmt{{false, false, true, false}};
auto got = fmt.format(List{multiline}); auto got = fmt.format(List{multiline});
auto* expect = R"(2:9: multiline auto* expect = R"(2:9: multiline
@ -166,7 +167,7 @@ the snake says quack
TEST_F(DiagFormatterTest, BasicWithMultiLineTab4) { TEST_F(DiagFormatterTest, BasicWithMultiLineTab4) {
Diagnostic multiline{Severity::Warning, Diagnostic multiline{Severity::Warning,
Source{Source::Range{{2, 9}, {4, 15}}, &file}, Source{Source::Range{{2, 9}, {4, 15}}, &file},
"multiline"}; "multiline", System::Test};
Formatter fmt{{false, false, true, false, 4u}}; Formatter fmt{{false, false, true, false, 4u}};
auto got = fmt.format(List{multiline}); auto got = fmt.format(List{multiline});
auto* expect = R"(2:9: multiline auto* expect = R"(2:9: multiline
@ -219,7 +220,7 @@ the snail says ???
TEST_F(DiagFormatterTest, RangeOOB) { TEST_F(DiagFormatterTest, RangeOOB) {
Formatter fmt{{true, true, true, true}}; Formatter fmt{{true, true, true, true}};
diag::List list; diag::List list;
list.add_error("oob", Source{{{10, 20}, {30, 20}}, &file}); list.add_error(System::Test, "oob", Source{{{10, 20}, {30, 20}}, &file});
auto got = fmt.format(list); auto got = fmt.format(list);
auto* expect = R"(file.name:10:20 error: oob auto* expect = R"(file.name:10:20 error: oob

View File

@ -47,7 +47,7 @@ namespace {
void AppendResourceBindings(std::vector<ResourceBinding>* dest, void AppendResourceBindings(std::vector<ResourceBinding>* dest,
const std::vector<ResourceBinding>& orig) { const std::vector<ResourceBinding>& orig) {
TINT_ASSERT(dest); TINT_ASSERT(Inspector, dest);
if (!dest) { if (!dest) {
return; return;
} }
@ -84,7 +84,7 @@ std::vector<EntryPoint> Inspector::GetEntryPoints() {
if (wgsize[0].overridable_const || wgsize[1].overridable_const || if (wgsize[0].overridable_const || wgsize[1].overridable_const ||
wgsize[2].overridable_const) { wgsize[2].overridable_const) {
// TODO(crbug.com/tint/713): Handle overridable constants. // TODO(crbug.com/tint/713): Handle overridable constants.
TINT_ASSERT(false); TINT_ASSERT(Inspector, false);
} }
for (auto* param : sem->Parameters()) { for (auto* param : sem->Parameters()) {
@ -528,7 +528,7 @@ void Inspector::AddEntryPointInOutVariables(
} }
auto* location = ast::GetDecoration<ast::LocationDecoration>(decorations); auto* location = ast::GetDecoration<ast::LocationDecoration>(decorations);
TINT_ASSERT(location != nullptr); TINT_ASSERT(Inspector, location != nullptr);
stage_variable.has_location_decoration = true; stage_variable.has_location_decoration = true;
stage_variable.location_decoration = location->value(); stage_variable.location_decoration = location->value();

View File

@ -120,11 +120,11 @@ class ClosedState {
const sem::Type* Type(uint32_t idx) const { const sem::Type* Type(uint32_t idx) const {
auto it = types_.find(idx); auto it = types_.find(idx);
if (it == types_.end()) { if (it == types_.end()) {
TINT_ICE(builder.Diagnostics()) TINT_ICE(Resolver, builder.Diagnostics())
<< "type with index " << idx << " is not closed"; << "type with index " << idx << " is not closed";
return nullptr; return nullptr;
} }
TINT_ASSERT(it != types_.end()); TINT_ASSERT(Resolver, it != types_.end());
return it->second; return it->second;
} }
@ -133,7 +133,7 @@ class ClosedState {
Number Num(uint32_t idx) const { Number Num(uint32_t idx) const {
auto it = numbers_.find(idx); auto it = numbers_.find(idx);
if (it == numbers_.end()) { if (it == numbers_.end()) {
TINT_ICE(builder.Diagnostics()) TINT_ICE(Resolver, builder.Diagnostics())
<< "number with index " << idx << " is not closed"; << "number with index " << idx << " is not closed";
return Number::invalid; return Number::invalid;
} }
@ -802,7 +802,7 @@ const sem::Intrinsic* Impl::Lookup(sem::IntrinsicType intrinsic_type,
ss << std::endl; ss << std::endl;
} }
} }
builder.Diagnostics().add_error(ss.str(), source); builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
return nullptr; return nullptr;
} }
@ -888,7 +888,7 @@ const sem::Intrinsic* Impl::Match(sem::IntrinsicType intrinsic_type,
if (!return_type) { if (!return_type) {
std::stringstream ss; std::stringstream ss;
PrintOverload(ss, overload, intrinsic_type); PrintOverload(ss, overload, intrinsic_type);
TINT_ICE(builder.Diagnostics()) TINT_ICE(Resolver, builder.Diagnostics())
<< "MatchState.Match() returned null for " << ss.str(); << "MatchState.Match() returned null for " << ss.str();
return nullptr; return nullptr;
} }

View File

@ -63,7 +63,7 @@ Program::Program(ProgramBuilder&& builder) {
// If the builder claims to be invalid, then we really should have an error // If the builder claims to be invalid, then we really should have an error
// message generated. If we find a situation where the program is not valid // message generated. If we find a situation where the program is not valid
// and there are no errors reported, add one here. // and there are no errors reported, add one here.
diagnostics_.add_error("invalid program generated"); diagnostics_.add_error(diag::System::Program, "invalid program generated");
} }
} }
@ -128,7 +128,7 @@ std::string Program::str(const ast::Node* node) const {
} }
void Program::AssertNotMoved() const { void Program::AssertNotMoved() const {
TINT_ASSERT(!moved_); TINT_ASSERT(Program, !moved_);
} }
} // namespace tint } // namespace tint

View File

@ -83,7 +83,7 @@ void ProgramBuilder::MarkAsMoved() {
void ProgramBuilder::AssertNotMoved() const { void ProgramBuilder::AssertNotMoved() const {
if (moved_) { if (moved_) {
TINT_ICE(const_cast<ProgramBuilder*>(this)->diagnostics_) TINT_ICE(ProgramBuilder, const_cast<ProgramBuilder*>(this)->diagnostics_)
<< "Attempting to use ProgramBuilder after it has been moved"; << "Attempting to use ProgramBuilder after it has been moved";
} }
} }

View File

@ -89,6 +89,7 @@ template <typename A, typename B>
void AssertProgramIDsEqual(A&& a, void AssertProgramIDsEqual(A&& a,
B&& b, B&& b,
bool if_valid, bool if_valid,
diag::System system,
const char* msg, const char* msg,
const char* file, const char* file,
size_t line) { size_t line) {
@ -101,25 +102,27 @@ void AssertProgramIDsEqual(A&& a,
return; // a or b were not valid return; // a or b were not valid
} }
diag::List diagnostics; diag::List diagnostics;
tint::InternalCompilerError(file, line, diagnostics) << msg; tint::InternalCompilerError(file, line, system, diagnostics) << msg;
} }
} // namespace detail } // namespace detail
/// TINT_ASSERT_PROGRAM_IDS_EQUAL(A, B) is a macro that asserts that the program /// TINT_ASSERT_PROGRAM_IDS_EQUAL(SYSTEM, A, B) is a macro that asserts that the
/// identifiers for A and B are equal. /// program identifiers for A and B are equal.
/// ///
/// TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(A, B) is a macro that asserts that /// TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(SYSTEM, A, B) is a macro that asserts
/// the program identifiers for A and B are equal, if both A and B have valid /// that the program identifiers for A and B are equal, if both A and B have
/// program identifiers. /// valid program identifiers.
#if TINT_CHECK_FOR_CROSS_PROGRAM_LEAKS #if TINT_CHECK_FOR_CROSS_PROGRAM_LEAKS
#define TINT_ASSERT_PROGRAM_IDS_EQUAL(a, b) \ #define TINT_ASSERT_PROGRAM_IDS_EQUAL(system, a, b) \
detail::AssertProgramIDsEqual( \ detail::AssertProgramIDsEqual(a, b, false, tint::diag::System::system, \
a, b, false, "TINT_ASSERT_PROGRAM_IDS_EQUAL(" #a ", " #b ")", __FILE__, \ "TINT_ASSERT_PROGRAM_IDS_EQUAL(" #system \
__LINE__) "," #a ", " #b ")", \
#define TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(a, b) \ __FILE__, __LINE__)
detail::AssertProgramIDsEqual( \ #define TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(system, a, b) \
a, b, true, "TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(" #a ", " #b ")", \ detail::AssertProgramIDsEqual( \
a, b, true, tint::diag::System::system, \
"TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(" #system ", " #a ", " #b ")", \
__FILE__, __LINE__) __FILE__, __LINE__)
#else #else
#define TINT_ASSERT_PROGRAM_IDS_EQUAL(a, b) \ #define TINT_ASSERT_PROGRAM_IDS_EQUAL(a, b) \

View File

@ -87,7 +87,7 @@ TEST_F(ProgramTest, Assert_Null_Function) {
} }
TEST_F(ProgramTest, DiagnosticsMove) { TEST_F(ProgramTest, DiagnosticsMove) {
Diagnostics().add_error("an error message"); Diagnostics().add_error(diag::System::Program, "an error message");
Program program_a(std::move(*this)); Program program_a(std::move(*this));
EXPECT_FALSE(program_a.IsValid()); EXPECT_FALSE(program_a.IsValid());

View File

@ -779,7 +779,7 @@ FunctionEmitter::StatementBlock::StatementBlock(StatementBlock&& other) =
FunctionEmitter::StatementBlock::~StatementBlock() = default; FunctionEmitter::StatementBlock::~StatementBlock() = default;
void FunctionEmitter::StatementBlock::Finalize(ProgramBuilder* pb) { void FunctionEmitter::StatementBlock::Finalize(ProgramBuilder* pb) {
TINT_ASSERT(!finalized_ /* Finalize() must only be called once */); TINT_ASSERT(Reader, !finalized_ /* Finalize() must only be called once */);
for (size_t i = 0; i < statements_.size(); i++) { for (size_t i = 0; i < statements_.size(); i++) {
if (auto* sb = statements_[i]->As<StatementBuilder>()) { if (auto* sb = statements_[i]->As<StatementBuilder>()) {
@ -795,7 +795,8 @@ void FunctionEmitter::StatementBlock::Finalize(ProgramBuilder* pb) {
} }
void FunctionEmitter::StatementBlock::Add(ast::Statement* statement) { void FunctionEmitter::StatementBlock::Add(ast::Statement* statement) {
TINT_ASSERT(!finalized_ /* Add() must not be called after Finalize() */); TINT_ASSERT(Reader,
!finalized_ /* Add() must not be called after Finalize() */);
statements_.emplace_back(statement); statements_.emplace_back(statement);
} }
@ -807,8 +808,8 @@ void FunctionEmitter::PushNewStatementBlock(const Construct* construct,
void FunctionEmitter::PushGuard(const std::string& guard_name, void FunctionEmitter::PushGuard(const std::string& guard_name,
uint32_t end_id) { uint32_t end_id) {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
TINT_ASSERT(!guard_name.empty()); TINT_ASSERT(Reader, !guard_name.empty());
// Guard control flow by the guard variable. Introduce a new // Guard control flow by the guard variable. Introduce a new
// if-selection with a then-clause ending at the same block // if-selection with a then-clause ending at the same block
// as the statement block at the top of the stack. // as the statement block at the top of the stack.
@ -825,7 +826,7 @@ void FunctionEmitter::PushGuard(const std::string& guard_name,
} }
void FunctionEmitter::PushTrueGuard(uint32_t end_id) { void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
const auto& top = statements_stack_.back(); const auto& top = statements_stack_.back();
auto* cond = MakeTrue(Source{}); auto* cond = MakeTrue(Source{});
@ -838,14 +839,14 @@ void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
} }
const ast::StatementList FunctionEmitter::ast_body() { const ast::StatementList FunctionEmitter::ast_body() {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
auto& entry = statements_stack_[0]; auto& entry = statements_stack_[0];
entry.Finalize(&builder_); entry.Finalize(&builder_);
return entry.GetStatements(); return entry.GetStatements();
} }
ast::Statement* FunctionEmitter::AddStatement(ast::Statement* statement) { ast::Statement* FunctionEmitter::AddStatement(ast::Statement* statement) {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
if (statement != nullptr) { if (statement != nullptr) {
statements_stack_.back().Add(statement); statements_stack_.back().Add(statement);
} }
@ -853,9 +854,9 @@ ast::Statement* FunctionEmitter::AddStatement(ast::Statement* statement) {
} }
ast::Statement* FunctionEmitter::LastStatement() { ast::Statement* FunctionEmitter::LastStatement() {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
auto& statement_list = statements_stack_.back().GetStatements(); auto& statement_list = statements_stack_.back().GetStatements();
TINT_ASSERT(!statement_list.empty()); TINT_ASSERT(Reader, !statement_list.empty());
return statement_list.back(); return statement_list.back();
} }
@ -877,7 +878,7 @@ bool FunctionEmitter::Emit() {
bool make_body_function = true; bool make_body_function = true;
if (ep_info_) { if (ep_info_) {
TINT_ASSERT(!ep_info_->inner_name.empty()); TINT_ASSERT(Reader, !ep_info_->inner_name.empty());
if (ep_info_->owns_inner_implementation) { if (ep_info_->owns_inner_implementation) {
// This is an entry point, and we want to emit it as a wrapper around // This is an entry point, and we want to emit it as a wrapper around
// an implementation function. // an implementation function.
@ -909,7 +910,7 @@ bool FunctionEmitter::Emit() {
} }
ast::BlockStatement* FunctionEmitter::MakeFunctionBody() { ast::BlockStatement* FunctionEmitter::MakeFunctionBody() {
TINT_ASSERT(statements_stack_.size() == 1); TINT_ASSERT(Reader, statements_stack_.size() == 1);
if (!EmitBody()) { if (!EmitBody()) {
return nullptr; return nullptr;
@ -950,8 +951,8 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
// have already been created. // have already been created.
for (uint32_t var_id : ep_info_->inputs) { for (uint32_t var_id : ep_info_->inputs) {
const auto* var = def_use_mgr_->GetDef(var_id); const auto* var = def_use_mgr_->GetDef(var_id);
TINT_ASSERT(var != nullptr); TINT_ASSERT(Reader, var != nullptr);
TINT_ASSERT(var->opcode() == SpvOpVariable); TINT_ASSERT(Reader, var->opcode() == SpvOpVariable);
auto* store_type = GetVariableStoreType(*var); auto* store_type = GetVariableStoreType(*var);
auto* forced_store_type = store_type; auto* forced_store_type = store_type;
ast::DecorationList param_decos; ast::DecorationList param_decos;
@ -1050,8 +1051,8 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
create<ast::BuiltinDecoration>(source, ast::Builtin::kPosition)); create<ast::BuiltinDecoration>(source, ast::Builtin::kPosition));
} else { } else {
const auto* var = def_use_mgr_->GetDef(var_id); const auto* var = def_use_mgr_->GetDef(var_id);
TINT_ASSERT(var != nullptr); TINT_ASSERT(Reader, var != nullptr);
TINT_ASSERT(var->opcode() == SpvOpVariable); TINT_ASSERT(Reader, var->opcode() == SpvOpVariable);
store_type = GetVariableStoreType(*var); store_type = GetVariableStoreType(*var);
param_type = store_type; param_type = store_type;
if (!parser_impl_.ConvertDecorationsForVariable(var_id, &param_type, if (!parser_impl_.ConvertDecorationsForVariable(var_id, &param_type,
@ -1502,7 +1503,7 @@ bool FunctionEmitter::LabelControlFlowConstructs() {
// block. Also mark the the most recent continue target for which we // block. Also mark the the most recent continue target for which we
// haven't reached the backedge block. // haven't reached the backedge block.
TINT_ASSERT(block_order_.size() > 0); TINT_ASSERT(Reader, block_order_.size() > 0);
constructs_.clear(); constructs_.clear();
const auto entry_id = block_order_[0]; const auto entry_id = block_order_[0];
@ -1523,8 +1524,8 @@ bool FunctionEmitter::LabelControlFlowConstructs() {
// A loop construct is added right after its associated continue construct. // A loop construct is added right after its associated continue construct.
// In that case, adjust the parent up. // In that case, adjust the parent up.
if (k == Construct::kLoop) { if (k == Construct::kLoop) {
TINT_ASSERT(parent); TINT_ASSERT(Reader, parent);
TINT_ASSERT(parent->kind == Construct::kContinue); TINT_ASSERT(Reader, parent->kind == Construct::kContinue);
scope_end_pos = parent->end_pos; scope_end_pos = parent->end_pos;
parent = parent->parent; parent = parent->parent;
} }
@ -1543,9 +1544,9 @@ bool FunctionEmitter::LabelControlFlowConstructs() {
for (uint32_t i = 0; i < block_order_.size(); ++i) { for (uint32_t i = 0; i < block_order_.size(); ++i) {
const auto block_id = block_order_[i]; const auto block_id = block_order_[i];
TINT_ASSERT(block_id > 0); TINT_ASSERT(Reader, block_id > 0);
auto* block_info = GetBlockInfo(block_id); auto* block_info = GetBlockInfo(block_id);
TINT_ASSERT(block_info); TINT_ASSERT(Reader, block_info);
if (enclosing.empty()) { if (enclosing.empty()) {
return Fail() << "internal error: too many merge blocks before block " return Fail() << "internal error: too many merge blocks before block "
@ -1619,7 +1620,7 @@ bool FunctionEmitter::LabelControlFlowConstructs() {
} }
} }
TINT_ASSERT(top); TINT_ASSERT(Reader, top);
block_info->construct = top; block_info->construct = top;
} }
@ -1828,9 +1829,9 @@ bool FunctionEmitter::ClassifyCFGEdges() {
// NEC(S) is the parent of NEC(T). // NEC(S) is the parent of NEC(T).
for (const auto src : block_order_) { for (const auto src : block_order_) {
TINT_ASSERT(src > 0); TINT_ASSERT(Reader, src > 0);
auto* src_info = GetBlockInfo(src); auto* src_info = GetBlockInfo(src);
TINT_ASSERT(src_info); TINT_ASSERT(Reader, src_info);
const auto src_pos = src_info->pos; const auto src_pos = src_info->pos;
const auto& src_construct = *(src_info->construct); const auto& src_construct = *(src_info->construct);
@ -1868,7 +1869,7 @@ bool FunctionEmitter::ClassifyCFGEdges() {
for (const auto dest : successors) { for (const auto dest : successors) {
const auto* dest_info = GetBlockInfo(dest); const auto* dest_info = GetBlockInfo(dest);
// We've already checked terminators are valid. // We've already checked terminators are valid.
TINT_ASSERT(dest_info); TINT_ASSERT(Reader, dest_info);
const auto dest_pos = dest_info->pos; const auto dest_pos = dest_info->pos;
// Insert the edge kind entry and keep a handle to update // Insert the edge kind entry and keep a handle to update
@ -1893,7 +1894,7 @@ bool FunctionEmitter::ClassifyCFGEdges() {
<< " (violates post-dominance rule)"; << " (violates post-dominance rule)";
} }
const auto* ct_info = GetBlockInfo(continue_construct->begin_id); const auto* ct_info = GetBlockInfo(continue_construct->begin_id);
TINT_ASSERT(ct_info); TINT_ASSERT(Reader, ct_info);
if (ct_info->header_for_continue != dest) { if (ct_info->header_for_continue != dest) {
return Fail() return Fail()
<< "Invalid backedge (" << src << "->" << dest << "Invalid backedge (" << src << "->" << dest
@ -2185,7 +2186,7 @@ bool FunctionEmitter::FindIfSelectionInternalHeaders() {
// The first clause might be a then-clause or an else-clause. // The first clause might be a then-clause or an else-clause.
const auto second_head = std::max(true_head_pos, false_head_pos); const auto second_head = std::max(true_head_pos, false_head_pos);
const auto end_first_clause_pos = second_head - 1; const auto end_first_clause_pos = second_head - 1;
TINT_ASSERT(end_first_clause_pos < block_order_.size()); TINT_ASSERT(Reader, end_first_clause_pos < block_order_.size());
const auto end_first_clause = block_order_[end_first_clause_pos]; const auto end_first_clause = block_order_[end_first_clause_pos];
uint32_t premerge_id = 0; uint32_t premerge_id = 0;
uint32_t if_break_id = 0; uint32_t if_break_id = 0;
@ -2405,15 +2406,15 @@ bool FunctionEmitter::EmitFunctionBodyStatements() {
// Upon entry, the statement stack has one entry representing the whole // Upon entry, the statement stack has one entry representing the whole
// function. // function.
TINT_ASSERT(!constructs_.empty()); TINT_ASSERT(Reader, !constructs_.empty());
Construct* function_construct = constructs_[0].get(); Construct* function_construct = constructs_[0].get();
TINT_ASSERT(function_construct != nullptr); TINT_ASSERT(Reader, function_construct != nullptr);
TINT_ASSERT(function_construct->kind == Construct::kFunction); TINT_ASSERT(Reader, function_construct->kind == Construct::kFunction);
// Make the first entry valid by filling in the construct field, which // Make the first entry valid by filling in the construct field, which
// had not been computed at the time the entry was first created. // had not been computed at the time the entry was first created.
// TODO(dneto): refactor how the first construct is created vs. // TODO(dneto): refactor how the first construct is created vs.
// this statements stack entry is populated. // this statements stack entry is populated.
TINT_ASSERT(statements_stack_.size() == 1); TINT_ASSERT(Reader, statements_stack_.size() == 1);
statements_stack_[0].SetConstruct(function_construct); statements_stack_[0].SetConstruct(function_construct);
for (auto block_id : block_order()) { for (auto block_id : block_order()) {
@ -2612,8 +2613,8 @@ bool FunctionEmitter::EmitBasicBlock(const BlockInfo& block_info) {
bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) { bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
// The block is the if-header block. So its construct is the if construct. // The block is the if-header block. So its construct is the if construct.
auto* construct = block_info.construct; auto* construct = block_info.construct;
TINT_ASSERT(construct->kind == Construct::kIfSelection); TINT_ASSERT(Reader, construct->kind == Construct::kIfSelection);
TINT_ASSERT(construct->begin_id == block_info.id); TINT_ASSERT(Reader, construct->begin_id == block_info.id);
const uint32_t true_head = block_info.true_head; const uint32_t true_head = block_info.true_head;
const uint32_t false_head = block_info.false_head; const uint32_t false_head = block_info.false_head;
@ -2757,8 +2758,8 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) { bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
// The block is the if-header block. So its construct is the if construct. // The block is the if-header block. So its construct is the if construct.
auto* construct = block_info.construct; auto* construct = block_info.construct;
TINT_ASSERT(construct->kind == Construct::kSwitchSelection); TINT_ASSERT(Reader, construct->kind == Construct::kSwitchSelection);
TINT_ASSERT(construct->begin_id == block_info.id); TINT_ASSERT(Reader, construct->begin_id == block_info.id);
const auto* branch = block_info.basic_block->terminator(); const auto* branch = block_info.basic_block->terminator();
const auto selector_id = branch->GetSingleWordInOperand(0); const auto selector_id = branch->GetSingleWordInOperand(0);
@ -2806,7 +2807,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
clause_heads[w] = clause_heads[r]; clause_heads[w] = clause_heads[r];
} }
// We know it's not empty because it always has at least a default clause. // We know it's not empty because it always has at least a default clause.
TINT_ASSERT(!clause_heads.empty()); TINT_ASSERT(Reader, !clause_heads.empty());
clause_heads.resize(w + 1); clause_heads.resize(w + 1);
} }
@ -3019,9 +3020,10 @@ ast::Statement* FunctionEmitter::MakeBranchDetailed(
// Unless forced, don't bother with a break at the end of a case/default // Unless forced, don't bother with a break at the end of a case/default
// clause. // clause.
const auto header = dest_info.header_for_merge; const auto header = dest_info.header_for_merge;
TINT_ASSERT(header != 0); TINT_ASSERT(Reader, header != 0);
const auto* exiting_construct = GetBlockInfo(header)->construct; const auto* exiting_construct = GetBlockInfo(header)->construct;
TINT_ASSERT(exiting_construct->kind == Construct::kSwitchSelection); TINT_ASSERT(Reader,
exiting_construct->kind == Construct::kSwitchSelection);
const auto candidate_next_case_pos = src_info.pos + 1; const auto candidate_next_case_pos = src_info.pos + 1;
// Leaving the last block from the last case? // Leaving the last block from the last case?
if (candidate_next_case_pos == dest_info.pos) { if (candidate_next_case_pos == dest_info.pos) {
@ -3165,7 +3167,7 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
// Emit declarations of hoisted variables, in index order. // Emit declarations of hoisted variables, in index order.
for (auto id : sorted_by_index(block_info.hoisted_ids)) { for (auto id : sorted_by_index(block_info.hoisted_ids)) {
const auto* def_inst = def_use_mgr_->GetDef(id); const auto* def_inst = def_use_mgr_->GetDef(id);
TINT_ASSERT(def_inst); TINT_ASSERT(Reader, def_inst);
auto* storage_type = auto* storage_type =
RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id); RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id);
AddStatement(create<ast::VariableDeclStatement>( AddStatement(create<ast::VariableDeclStatement>(
@ -3178,9 +3180,9 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
// Emit declarations of phi state variables, in index order. // Emit declarations of phi state variables, in index order.
for (auto id : sorted_by_index(block_info.phis_needing_state_vars)) { for (auto id : sorted_by_index(block_info.phis_needing_state_vars)) {
const auto* def_inst = def_use_mgr_->GetDef(id); const auto* def_inst = def_use_mgr_->GetDef(id);
TINT_ASSERT(def_inst); TINT_ASSERT(Reader, def_inst);
const auto phi_var_name = GetDefInfo(id)->phi_var; const auto phi_var_name = GetDefInfo(id)->phi_var;
TINT_ASSERT(!phi_var_name.empty()); TINT_ASSERT(Reader, !phi_var_name.empty());
auto* var = builder_.Var( auto* var = builder_.Var(
phi_var_name, phi_var_name,
parser_impl_.ConvertType(def_inst->type_id())->Build(builder_)); parser_impl_.ConvertType(def_inst->type_id())->Build(builder_));
@ -3382,7 +3384,7 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
if (auto* arr = lhs.type->As<Array>()) { if (auto* arr = lhs.type->As<Array>()) {
lhs.type = arr->type; lhs.type = arr->type;
} }
TINT_ASSERT(lhs.type); TINT_ASSERT(Reader, lhs.type);
break; break;
default: default:
break; break;
@ -4008,7 +4010,7 @@ TypedExpression FunctionEmitter::MakeAccessChain(
const auto pointer_type_id = const auto pointer_type_id =
type_mgr_->FindPointerToType(pointee_type_id, storage_class); type_mgr_->FindPointerToType(pointee_type_id, storage_class);
auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref); auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref);
TINT_ASSERT(type && type->Is<Reference>()); TINT_ASSERT(Reader, type && type->Is<Reference>());
current_expr = TypedExpression{type, next_expr}; current_expr = TypedExpression{type, next_expr};
} }
return current_expr; return current_expr;
@ -4206,7 +4208,7 @@ TypedExpression FunctionEmitter::MakeVectorShuffle(
source, expr.expr, Swizzle(index))); source, expr.expr, Swizzle(index)));
} else if (index < vec0_len + vec1_len) { } else if (index < vec0_len + vec1_len) {
const auto sub_index = index - vec0_len; const auto sub_index = index - vec0_len;
TINT_ASSERT(sub_index < kMaxVectorLen); TINT_ASSERT(Reader, sub_index < kMaxVectorLen);
auto expr = MakeExpression(vec1_id); auto expr = MakeExpression(vec1_id);
if (!expr) { if (!expr) {
return {}; return {};
@ -4511,7 +4513,7 @@ const Construct* FunctionEmitter::GetEnclosingScope(uint32_t first_pos,
uint32_t last_pos) const { uint32_t last_pos) const {
const auto* enclosing_construct = const auto* enclosing_construct =
GetBlockInfo(block_order_[first_pos])->construct; GetBlockInfo(block_order_[first_pos])->construct;
TINT_ASSERT(enclosing_construct != nullptr); TINT_ASSERT(Reader, enclosing_construct != nullptr);
// Constructs are strictly nesting, so follow parent pointers // Constructs are strictly nesting, so follow parent pointers
while (enclosing_construct && while (enclosing_construct &&
!enclosing_construct->ScopeContainsPos(last_pos)) { !enclosing_construct->ScopeContainsPos(last_pos)) {
@ -4523,7 +4525,7 @@ const Construct* FunctionEmitter::GetEnclosingScope(uint32_t first_pos,
sibling_loop ? sibling_loop : enclosing_construct->parent; sibling_loop ? sibling_loop : enclosing_construct->parent;
} }
// At worst, we go all the way out to the function construct. // At worst, we go all the way out to the function construct.
TINT_ASSERT(enclosing_construct != nullptr); TINT_ASSERT(Reader, enclosing_construct != nullptr);
return enclosing_construct; return enclosing_construct;
} }
@ -5270,11 +5272,11 @@ ast::Expression* FunctionEmitter::ConvertTexelForStorage(
// The texel type is always a 4-element vector. // The texel type is always a 4-element vector.
const uint32_t dest_count = 4u; const uint32_t dest_count = 4u;
TINT_ASSERT(dest_type->Is<Vector>() && TINT_ASSERT(Reader, dest_type->Is<Vector>() &&
dest_type->As<Vector>()->size == dest_count); dest_type->As<Vector>()->size == dest_count);
TINT_ASSERT(dest_type->IsFloatVector() || TINT_ASSERT(Reader, dest_type->IsFloatVector() ||
dest_type->IsUnsignedIntegerVector() || dest_type->IsUnsignedIntegerVector() ||
dest_type->IsSignedIntegerVector()); dest_type->IsSignedIntegerVector());
if (src_type == dest_type) { if (src_type == dest_type) {
return texel.expr; return texel.expr;
@ -5294,7 +5296,7 @@ ast::Expression* FunctionEmitter::ConvertTexelForStorage(
} }
const auto required_count = parser_impl_.GetChannelCountForFormat(format); const auto required_count = parser_impl_.GetChannelCountForFormat(format);
TINT_ASSERT(0 < required_count && required_count <= 4); TINT_ASSERT(Reader, 0 < required_count && required_count <= 4);
const uint32_t src_count = const uint32_t src_count =
src_type->IsScalar() ? 1 : src_type->As<Vector>()->size; src_type->IsScalar() ? 1 : src_type->As<Vector>()->size;

View File

@ -1017,7 +1017,7 @@ class FunctionEmitter {
/// @return the built StatementBuilder /// @return the built StatementBuilder
template <typename T, typename... ARGS> template <typename T, typename... ARGS>
T* AddStatementBuilder(ARGS&&... args) { T* AddStatementBuilder(ARGS&&... args) {
TINT_ASSERT(!statements_stack_.empty()); TINT_ASSERT(Reader, !statements_stack_.empty());
return statements_stack_.back().AddStatementBuilder<T>( return statements_stack_.back().AddStatementBuilder<T>(
std::forward<ARGS>(args)...); std::forward<ARGS>(args)...);
} }

View File

@ -123,7 +123,7 @@ std::string Namer::FindUnusedDerivedName(const std::string& base_name) const {
std::string Namer::MakeDerivedName(const std::string& base_name) { std::string Namer::MakeDerivedName(const std::string& base_name) {
auto result = FindUnusedDerivedName(base_name); auto result = FindUnusedDerivedName(base_name);
const bool registered = RegisterWithoutId(result); const bool registered = RegisterWithoutId(result);
TINT_ASSERT(registered); TINT_ASSERT(Reader, registered);
return result; return result;
} }

View File

@ -29,7 +29,7 @@ Program Parse(const std::vector<uint32_t>& input) {
ProgramBuilder& builder = parser.builder(); ProgramBuilder& builder = parser.builder();
if (!parsed) { if (!parsed) {
// TODO(bclayton): Migrate spirv::ParserImpl to using diagnostics. // TODO(bclayton): Migrate spirv::ParserImpl to using diagnostics.
builder.Diagnostics().add_error(parser.error()); builder.Diagnostics().add_error(diag::System::Reader, parser.error());
return Program(std::move(builder)); return Program(std::move(builder));
} }

View File

@ -833,8 +833,8 @@ bool ParserImpl::RegisterEntryPoints() {
// Reuse the inner implementation owned by the first entry point. // Reuse the inner implementation owned by the first entry point.
inner_implementation_name = where->second[0].inner_name; inner_implementation_name = where->second[0].inner_name;
} }
TINT_ASSERT(!inner_implementation_name.empty()); TINT_ASSERT(Reader, !inner_implementation_name.empty());
TINT_ASSERT(ep_name != inner_implementation_name); TINT_ASSERT(Reader, ep_name != inner_implementation_name);
tint::UniqueVector<uint32_t> inputs; tint::UniqueVector<uint32_t> inputs;
tint::UniqueVector<uint32_t> outputs; tint::UniqueVector<uint32_t> outputs;

View File

@ -40,7 +40,7 @@ Program ParseAndBuild(std::string spirv) {
auto p = std::make_unique<ParserImpl>(test::Assemble(preamble + spirv)); auto p = std::make_unique<ParserImpl>(test::Assemble(preamble + spirv));
if (!p->BuildAndParseInternalModule()) { if (!p->BuildAndParseInternalModule()) {
ProgramBuilder builder; ProgramBuilder builder;
builder.Diagnostics().add_error(p->error()); builder.Diagnostics().add_error(diag::System::Reader, p->error());
return Program(std::move(builder)); return Program(std::move(builder));
} }
return p->program(); return p->program();

View File

@ -269,14 +269,15 @@ ParserImpl::Failure::Errored ParserImpl::add_error(const Token& t,
ParserImpl::Failure::Errored ParserImpl::add_error(const Source& source, ParserImpl::Failure::Errored ParserImpl::add_error(const Source& source,
const std::string& err) { const std::string& err) {
if (silence_errors_ == 0) { if (silence_errors_ == 0) {
builder_.Diagnostics().add_error(err, source); builder_.Diagnostics().add_error(diag::System::Reader, err, source);
} }
return Failure::kErrored; return Failure::kErrored;
} }
void ParserImpl::deprecated(const Source& source, const std::string& msg) { void ParserImpl::deprecated(const Source& source, const std::string& msg) {
builder_.Diagnostics().add_warning( builder_.Diagnostics().add_warning(
"use of deprecated language feature: " + msg, source); diag::System::Reader, "use of deprecated language feature: " + msg,
source);
} }
Token ParserImpl::next() { Token ParserImpl::next() {
@ -3298,7 +3299,7 @@ T ParserImpl::sync(Token::Type tok, F&& body) {
--parse_depth_; --parse_depth_;
if (sync_tokens_.back() != tok) { if (sync_tokens_.back() != tok) {
TINT_ICE(builder_.Diagnostics()) << "sync_tokens is out of sync"; TINT_ICE(Reader, builder_.Diagnostics()) << "sync_tokens is out of sync";
} }
sync_tokens_.pop_back(); sync_tokens_.pop_back();

View File

@ -112,7 +112,7 @@ class ParserImpl {
/// return type will always be a pointer to a non-pointer type. #errored /// return type will always be a pointer to a non-pointer type. #errored
/// must be false to call. /// must be false to call.
inline typename detail::OperatorArrow<T>::type operator->() { inline typename detail::OperatorArrow<T>::type operator->() {
TINT_ASSERT(!errored); TINT_ASSERT(Reader, !errored);
return detail::OperatorArrow<T>::ptr(value); return detail::OperatorArrow<T>::ptr(value);
} }
@ -183,7 +183,7 @@ class ParserImpl {
/// return type will always be a pointer to a non-pointer type. #errored /// return type will always be a pointer to a non-pointer type. #errored
/// must be false to call. /// must be false to call.
inline typename detail::OperatorArrow<T>::type operator->() { inline typename detail::OperatorArrow<T>::type operator->() {
TINT_ASSERT(!errored); TINT_ASSERT(Reader, !errored);
return detail::OperatorArrow<T>::ptr(value); return detail::OperatorArrow<T>::ptr(value);
} }

File diff suppressed because it is too large Load Diff

View File

@ -409,6 +409,21 @@ class Resolver {
/// @param node the AST node. /// @param node the AST node.
void Mark(const ast::Node* node); void Mark(const ast::Node* node);
/// Adds the given error message to the diagnostics
/// [DEPRECATED] Remove all codes
void AddError(const char* code,
const std::string& msg,
const Source& source) const;
/// Adds the given error message to the diagnostics
void AddError(const std::string& msg, const Source& source) const;
/// Adds the given warning message to the diagnostics
void AddWarning(const std::string& msg, const Source& source) const;
/// Adds the given note message to the diagnostics
void AddNote(const std::string& msg, const Source& source) const;
template <typename CALLBACK> template <typename CALLBACK>
void TraverseCallChain(FunctionInfo* from, void TraverseCallChain(FunctionInfo* from,
FunctionInfo* to, FunctionInfo* to,

View File

@ -35,7 +35,7 @@ Array::Array(const Type* element,
size_(size), size_(size),
stride_(stride), stride_(stride),
implicit_stride_(implicit_stride) { implicit_stride_(implicit_stride) {
TINT_ASSERT(element_); TINT_ASSERT(Semantic, element_);
} }
std::string Array::type_name() const { std::string Array::type_name() const {

View File

@ -23,7 +23,7 @@ namespace tint {
namespace sem { namespace sem {
Atomic::Atomic(const sem::Type* subtype) : subtype_(subtype) { Atomic::Atomic(const sem::Type* subtype) : subtype_(subtype) {
TINT_ASSERT(!subtype->Is<Reference>()); TINT_ASSERT(AST, !subtype->Is<Reference>());
} }
std::string Atomic::type_name() const { std::string Atomic::type_name() const {

View File

@ -23,7 +23,7 @@ namespace sem {
CallTarget::CallTarget(sem::Type* return_type, const ParameterList& parameters) CallTarget::CallTarget(sem::Type* return_type, const ParameterList& parameters)
: return_type_(return_type), parameters_(parameters) { : return_type_(return_type), parameters_(parameters) {
TINT_ASSERT(return_type); TINT_ASSERT(Semantic, return_type);
} }
CallTarget::~CallTarget() = default; CallTarget::~CallTarget() = default;

View File

@ -32,7 +32,7 @@ bool IsValidDepthDimension(ast::TextureDimension dim) {
} // namespace } // namespace
DepthTexture::DepthTexture(ast::TextureDimension dim) : Base(dim) { DepthTexture::DepthTexture(ast::TextureDimension dim) : Base(dim) {
TINT_ASSERT(IsValidDepthDimension(dim)); TINT_ASSERT(Semantic, IsValidDepthDimension(dim));
} }
DepthTexture::DepthTexture(DepthTexture&&) = default; DepthTexture::DepthTexture(DepthTexture&&) = default;

View File

@ -23,7 +23,7 @@ Expression::Expression(const ast::Expression* declaration,
const sem::Type* type, const sem::Type* type,
Statement* statement) Statement* statement)
: declaration_(declaration), type_(type), statement_(statement) { : declaration_(declaration), type_(type), statement_(statement) {
TINT_ASSERT(type_); TINT_ASSERT(Semantic, type_);
} }
} // namespace sem } // namespace sem

View File

@ -70,7 +70,7 @@ class Info {
void Add(const AST_OR_TYPE* node, void Add(const AST_OR_TYPE* node,
const SemanticNodeTypeFor<AST_OR_TYPE>* sem_node) { const SemanticNodeTypeFor<AST_OR_TYPE>* sem_node) {
// Check there's no semantic info already existing for the node // Check there's no semantic info already existing for the node
TINT_ASSERT(Get(node) == nullptr); TINT_ASSERT(Semantic, Get(node) == nullptr);
map.emplace(node, sem_node); map.emplace(node, sem_node);
} }

View File

@ -27,10 +27,10 @@ Matrix::Matrix(Vector* column_type, uint32_t columns)
column_type_(column_type), column_type_(column_type),
rows_(column_type->size()), rows_(column_type->size()),
columns_(columns) { columns_(columns) {
TINT_ASSERT(rows_ > 1); TINT_ASSERT(AST, rows_ > 1);
TINT_ASSERT(rows_ < 5); TINT_ASSERT(AST, rows_ < 5);
TINT_ASSERT(columns_ > 1); TINT_ASSERT(AST, columns_ > 1);
TINT_ASSERT(columns_ < 5); TINT_ASSERT(AST, columns_ < 5);
} }
Matrix::Matrix(Matrix&&) = default; Matrix::Matrix(Matrix&&) = default;

View File

@ -24,7 +24,7 @@ namespace sem {
MultisampledTexture::MultisampledTexture(ast::TextureDimension dim, MultisampledTexture::MultisampledTexture(ast::TextureDimension dim,
const Type* type) const Type* type)
: Base(dim), type_(type) { : Base(dim), type_(type) {
TINT_ASSERT(type_); TINT_ASSERT(Semantic, type_);
} }
MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default; MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default;

View File

@ -26,8 +26,8 @@ Pointer::Pointer(const Type* subtype,
ast::StorageClass storage_class, ast::StorageClass storage_class,
ast::Access access) ast::Access access)
: subtype_(subtype), storage_class_(storage_class), access_(access) { : subtype_(subtype), storage_class_(storage_class), access_(access) {
TINT_ASSERT(!subtype->Is<Reference>()); TINT_ASSERT(Semantic, !subtype->Is<Reference>());
TINT_ASSERT(access != ast::Access::kUndefined); TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
} }
std::string Pointer::type_name() const { std::string Pointer::type_name() const {

View File

@ -25,8 +25,8 @@ Reference::Reference(const Type* subtype,
ast::StorageClass storage_class, ast::StorageClass storage_class,
ast::Access access) ast::Access access)
: subtype_(subtype), storage_class_(storage_class), access_(access) { : subtype_(subtype), storage_class_(storage_class), access_(access) {
TINT_ASSERT(!subtype->Is<Reference>()); TINT_ASSERT(Semantic, !subtype->Is<Reference>());
TINT_ASSERT(access != ast::Access::kUndefined); TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
} }
std::string Reference::type_name() const { std::string Reference::type_name() const {

View File

@ -23,7 +23,7 @@ namespace sem {
SampledTexture::SampledTexture(ast::TextureDimension dim, const Type* type) SampledTexture::SampledTexture(ast::TextureDimension dim, const Type* type)
: Base(dim), type_(type) { : Base(dim), type_(type) {
TINT_ASSERT(type_); TINT_ASSERT(Semantic, type_);
} }
SampledTexture::SampledTexture(SampledTexture&&) = default; SampledTexture::SampledTexture(SampledTexture&&) = default;

View File

@ -47,7 +47,7 @@ Statement::Statement(const ast::Statement* declaration, const Statement* parent)
} }
} }
} }
TINT_ASSERT(statement_is_continuing_for_loop); TINT_ASSERT(Semantic, statement_is_continuing_for_loop);
} }
} }
} }

View File

@ -23,8 +23,8 @@ namespace sem {
Vector::Vector(Type const* subtype, uint32_t size) Vector::Vector(Type const* subtype, uint32_t size)
: subtype_(subtype), size_(size) { : subtype_(subtype), size_(size) {
TINT_ASSERT(size_ > 1); TINT_ASSERT(Semantic, size_ > 1);
TINT_ASSERT(size_ < 5); TINT_ASSERT(Semantic, size_ < 5);
} }
Vector::Vector(Vector&&) = default; Vector::Vector(Vector&&) = default;

View File

@ -32,7 +32,8 @@ Symbol& Symbol::operator=(const Symbol& o) = default;
Symbol& Symbol::operator=(Symbol&& o) = default; Symbol& Symbol::operator=(Symbol&& o) = default;
bool Symbol::operator==(const Symbol& other) const { bool Symbol::operator==(const Symbol& other) const {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(program_id_, other.program_id_); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Symbol, program_id_,
other.program_id_);
return val_ == other.val_; return val_ == other.val_;
} }

View File

@ -54,7 +54,7 @@ Symbol SymbolTable::Get(const std::string& name) const {
} }
std::string SymbolTable::NameFor(const Symbol symbol) const { std::string SymbolTable::NameFor(const Symbol symbol) const {
TINT_ASSERT_PROGRAM_IDS_EQUAL(program_id_, symbol); TINT_ASSERT_PROGRAM_IDS_EQUAL(Symbol, program_id_, symbol);
auto it = symbol_to_name_.find(symbol); auto it = symbol_to_name_.find(symbol);
if (it == symbol_to_name_.end()) { if (it == symbol_to_name_.end()) {
return symbol.to_str(); return symbol.to_str();

View File

@ -38,6 +38,7 @@ Output ArrayLengthFromUniform::Run(const Program* in, const DataMap& data) {
auto* cfg = data.Get<Config>(); auto* cfg = data.Get<Config>();
if (cfg == nullptr) { if (cfg == nullptr) {
out.Diagnostics().add_error( out.Diagnostics().add_error(
diag::System::Transform,
"missing transform data for ArrayLengthFromUniform"); "missing transform data for ArrayLengthFromUniform");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }
@ -95,13 +96,13 @@ Output ArrayLengthFromUniform::Run(const Program* in, const DataMap& data) {
// have been run before this transform. // have been run before this transform.
auto* param = call_expr->params()[0]->As<ast::UnaryOpExpression>(); auto* param = call_expr->params()[0]->As<ast::UnaryOpExpression>();
if (!param || param->op() != ast::UnaryOp::kAddressOf) { if (!param || param->op() != ast::UnaryOp::kAddressOf) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected form of arrayLength argument to be &resource.array"; << "expected form of arrayLength argument to be &resource.array";
break; break;
} }
auto* accessor = param->expr()->As<ast::MemberAccessorExpression>(); auto* accessor = param->expr()->As<ast::MemberAccessorExpression>();
if (!accessor) { if (!accessor) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected form of arrayLength argument to be &resource.array"; << "expected form of arrayLength argument to be &resource.array";
break; break;
} }
@ -109,7 +110,7 @@ Output ArrayLengthFromUniform::Run(const Program* in, const DataMap& data) {
auto* storage_buffer_sem = auto* storage_buffer_sem =
sem.Get(storage_buffer_expr)->As<sem::VariableUser>(); sem.Get(storage_buffer_expr)->As<sem::VariableUser>();
if (!storage_buffer_sem) { if (!storage_buffer_sem) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected form of arrayLength argument to be &resource.array"; << "expected form of arrayLength argument to be &resource.array";
break; break;
} }
@ -119,9 +120,10 @@ Output ArrayLengthFromUniform::Run(const Program* in, const DataMap& data) {
auto idx_itr = cfg->bindpoint_to_size_index.find(binding); auto idx_itr = cfg->bindpoint_to_size_index.find(binding);
if (idx_itr == cfg->bindpoint_to_size_index.end()) { if (idx_itr == cfg->bindpoint_to_size_index.end()) {
ctx.dst->Diagnostics().add_error( ctx.dst->Diagnostics().add_error(
diag::System::Transform,
"missing size index mapping for binding point (" + "missing size index mapping for binding point (" +
std::to_string(binding.group) + "," + std::to_string(binding.group) + "," +
std::to_string(binding.binding) + ")"); std::to_string(binding.binding) + ")");
continue; continue;
} }

View File

@ -45,6 +45,7 @@ Output BindingRemapper::Run(const Program* in, const DataMap& datamap) {
auto* remappings = datamap.Get<Remappings>(); auto* remappings = datamap.Get<Remappings>();
if (!remappings) { if (!remappings) {
out.Diagnostics().add_error( out.Diagnostics().add_error(
diag::System::Transform,
"BindingRemapper did not find the remapping data"); "BindingRemapper did not find the remapping data");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }

View File

@ -74,7 +74,8 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
auto* limit = b.Sub(arr_len, b.Expr(1u)); auto* limit = b.Sub(arr_len, b.Expr(1u));
new_idx = b.Call("min", b.Construct<u32>(ctx->Clone(old_idx)), limit); new_idx = b.Call("min", b.Construct<u32>(ctx->Clone(old_idx)), limit);
} else { } else {
diags.add_error("invalid 0 size", expr->source()); diags.add_error(diag::System::Transform, "invalid 0 size",
expr->source());
return nullptr; return nullptr;
} }
} else if (auto* c = old_idx->As<ast::ScalarConstructorExpression>()) { } else if (auto* c = old_idx->As<ast::ScalarConstructorExpression>()) {
@ -86,7 +87,8 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
} else if (auto* uint = lit->As<ast::UintLiteral>()) { } else if (auto* uint = lit->As<ast::UintLiteral>()) {
new_idx = b.Expr(std::min(uint->value(), size - 1)); new_idx = b.Expr(std::min(uint->value(), size - 1));
} else { } else {
diags.add_error("unknown scalar constructor type for accessor", diags.add_error(diag::System::Transform,
"unknown scalar constructor type for accessor",
expr->source()); expr->source());
return nullptr; return nullptr;
} }

View File

@ -134,7 +134,7 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) {
auto* arg = call_expr->params()[0]; auto* arg = call_expr->params()[0];
auto* address_of = arg->As<ast::UnaryOpExpression>(); auto* address_of = arg->As<ast::UnaryOpExpression>();
if (!address_of || address_of->op() != ast::UnaryOp::kAddressOf) { if (!address_of || address_of->op() != ast::UnaryOp::kAddressOf) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "arrayLength() expected pointer to member access, got " << "arrayLength() expected pointer to member access, got "
<< address_of->TypeInfo().name; << address_of->TypeInfo().name;
} }
@ -142,7 +142,7 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) {
auto* accessor = array_expr->As<ast::MemberAccessorExpression>(); auto* accessor = array_expr->As<ast::MemberAccessorExpression>();
if (!accessor) { if (!accessor) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "arrayLength() expected pointer to member access, got " << "arrayLength() expected pointer to member access, got "
"pointer to " "pointer to "
<< array_expr->TypeInfo().name; << array_expr->TypeInfo().name;
@ -158,7 +158,7 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) {
auto buffer_size = get_buffer_size_intrinsic(storage_buffer_type); auto buffer_size = get_buffer_size_intrinsic(storage_buffer_type);
if (!storage_buffer_type) { if (!storage_buffer_type) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "arrayLength(X.Y) expected X to be sem::Struct, got " << "arrayLength(X.Y) expected X to be sem::Struct, got "
<< storage_buffer_type->FriendlyName(ctx.src->Symbols()); << storage_buffer_type->FriendlyName(ctx.src->Symbols());
break; break;

View File

@ -69,6 +69,7 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap& data) {
auto* cfg = data.Get<Config>(); auto* cfg = data.Get<Config>();
if (cfg == nullptr) { if (cfg == nullptr) {
out.Diagnostics().add_error( out.Diagnostics().add_error(
diag::System::Transform,
"missing transform data for CanonicalizeEntryPointIO"); "missing transform data for CanonicalizeEntryPointIO");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }
@ -146,7 +147,8 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap& data) {
ast::ExpressionList init_values; ast::ExpressionList init_values;
for (auto* member : str->Members()) { for (auto* member : str->Members()) {
if (member->Type()->Is<sem::Struct>()) { if (member->Type()->Is<sem::Struct>()) {
TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct"; TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "nested pipeline IO struct";
} }
if (cfg->builtin_style == BuiltinStyle::kParameter && if (cfg->builtin_style == BuiltinStyle::kParameter &&
@ -239,7 +241,8 @@ Output CanonicalizeEntryPointIO::Run(const Program* in, const DataMap& data) {
// Rebuild struct with only the entry point IO attributes. // Rebuild struct with only the entry point IO attributes.
for (auto* member : str->Members()) { for (auto* member : str->Members()) {
if (member->Type()->Is<sem::Struct>()) { if (member->Type()->Is<sem::Struct>()) {
TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct"; TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "nested pipeline IO struct";
} }
ast::DecorationList new_decorations = RemoveDecorations( ast::DecorationList new_decorations = RemoveDecorations(

View File

@ -352,7 +352,7 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak; op = DecomposeMemoryAccess::Intrinsic::Op::kAtomicCompareExchangeWeak;
break; break;
default: default:
TINT_ICE(builder->Diagnostics()) TINT_ICE(Transform, builder->Diagnostics())
<< "invalid IntrinsicType for DecomposeMemoryAccess::Intrinsic: " << "invalid IntrinsicType for DecomposeMemoryAccess::Intrinsic: "
<< ty->type_name(); << ty->type_name();
break; break;
@ -435,7 +435,7 @@ struct DecomposeMemoryAccess::State {
/// @param expr the expression that performs the access /// @param expr the expression that performs the access
/// @param access the access /// @param access the access
void AddAccess(ast::Expression* expr, BufferAccess&& access) { void AddAccess(ast::Expression* expr, BufferAccess&& access) {
TINT_ASSERT(access.type); TINT_ASSERT(Transform, access.type);
accesses.emplace(expr, std::move(access)); accesses.emplace(expr, std::move(access));
expression_order.emplace_back(expr); expression_order.emplace_back(expr);
} }
@ -672,7 +672,7 @@ struct DecomposeMemoryAccess::State {
auto* atomic = IntrinsicAtomicFor(ctx.dst, op, el_ty); auto* atomic = IntrinsicAtomicFor(ctx.dst, op, el_ty);
if (atomic == nullptr) { if (atomic == nullptr) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "IntrinsicAtomicFor() returned nullptr for op " << op << "IntrinsicAtomicFor() returned nullptr for op " << op
<< " and type " << el_ty->type_name(); << " and type " << el_ty->type_name();
} }

View File

@ -58,7 +58,7 @@ Output ExternalTextureTransform::Run(const Program* in, const DataMap&) {
->Is<sem::ExternalTexture>()) { ->Is<sem::ExternalTexture>()) {
if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad && if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad &&
call_expr->params().size() != 2) { call_expr->params().size() != 2) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected textureLoad call with a texture_external to " << "expected textureLoad call with a texture_external to "
"have 2 parameters, found " "have 2 parameters, found "
<< call_expr->params().size() << " parameters"; << call_expr->params().size() << " parameters";
@ -67,7 +67,7 @@ Output ExternalTextureTransform::Run(const Program* in, const DataMap&) {
if (intrinsic->Type() == if (intrinsic->Type() ==
sem::IntrinsicType::kTextureSampleLevel && sem::IntrinsicType::kTextureSampleLevel &&
call_expr->params().size() != 3) { call_expr->params().size() != 3) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "expected textureSampleLevel call with a " << "expected textureSampleLevel call with a "
"texture_external to have 3 parameters, found " "texture_external to have 3 parameters, found "
<< call_expr->params().size() << " parameters"; << call_expr->params().size() << " parameters";

View File

@ -67,7 +67,7 @@ struct Value {
operator bool() const { return Valid(); } operator bool() const { return Valid(); }
void Append(const Value& value) { void Append(const Value& value) {
TINT_ASSERT(value.type == type); TINT_ASSERT(Transform, value.type == type);
elems.insert(elems.end(), value.elems.begin(), value.elems.end()); elems.insert(elems.end(), value.elems.begin(), value.elems.end());
} }
@ -89,7 +89,7 @@ struct Value {
return func(elems[index].bool_); return func(elems[index].bool_);
} }
} }
TINT_ASSERT(false && "Unreachable"); TINT_ASSERT(Transform, false && "Unreachable");
return func(~0); return func(~0);
} }
}; };
@ -105,7 +105,7 @@ Value::Type AstToValueType(ast::Type* t) {
} else if (t->Is<ast::Bool>()) { } else if (t->Is<ast::Bool>()) {
return Value::Type::bool_; return Value::Type::bool_;
} }
TINT_ASSERT(false && "Invalid type"); TINT_ASSERT(Transform, false && "Invalid type");
return {}; return {};
} }
@ -193,7 +193,7 @@ Value Fold(const ast::ScalarConstructorExpression* scalar_ctor) {
if (auto* lit = literal->As<ast::BoolLiteral>()) { if (auto* lit = literal->As<ast::BoolLiteral>()) {
return {lit->IsTrue()}; return {lit->IsTrue()};
} }
TINT_ASSERT(false && "Unreachable"); TINT_ASSERT(Transform, false && "Unreachable");
return {}; return {};
} }

View File

@ -52,7 +52,7 @@ Output PromoteInitializersToConstVar::Run(const Program* in, const DataMap&) {
if (auto* src_init = src_node->As<ast::TypeConstructorExpression>()) { if (auto* src_init = src_node->As<ast::TypeConstructorExpression>()) {
auto* src_sem_expr = ctx.src->Sem().Get(src_init); auto* src_sem_expr = ctx.src->Sem().Get(src_init);
if (!src_sem_expr) { if (!src_sem_expr) {
TINT_ICE(ctx.dst->Diagnostics()) TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "ast::TypeConstructorExpression has no semantic expression node"; << "ast::TypeConstructorExpression has no semantic expression node";
continue; continue;
} }

View File

@ -857,7 +857,7 @@ Output Renamer::Run(const Program* in, const DataMap&) {
if (auto* member = node->As<ast::MemberAccessorExpression>()) { if (auto* member = node->As<ast::MemberAccessorExpression>()) {
auto* sem = in->Sem().Get(member); auto* sem = in->Sem().Get(member);
if (!sem) { if (!sem) {
TINT_ICE(out.Diagnostics()) TINT_ICE(Transform, out.Diagnostics())
<< "MemberAccessorExpression has no semantic info"; << "MemberAccessorExpression has no semantic info";
continue; continue;
} }
@ -867,7 +867,8 @@ Output Renamer::Run(const Program* in, const DataMap&) {
} else if (auto* call = node->As<ast::CallExpression>()) { } else if (auto* call = node->As<ast::CallExpression>()) {
auto* sem = in->Sem().Get(call); auto* sem = in->Sem().Get(call);
if (!sem) { if (!sem) {
TINT_ICE(out.Diagnostics()) << "CallExpression has no semantic info"; TINT_ICE(Transform, out.Diagnostics())
<< "CallExpression has no semantic info";
continue; continue;
} }
if (sem->Target()->Is<sem::Intrinsic>()) { if (sem->Target()->Is<sem::Intrinsic>()) {

View File

@ -35,7 +35,8 @@ Output SingleEntryPoint::Run(const Program* in, const DataMap& data) {
auto* cfg = data.Get<Config>(); auto* cfg = data.Get<Config>();
if (cfg == nullptr) { if (cfg == nullptr) {
out.Diagnostics().add_error("missing transform data for SingleEntryPoint"); out.Diagnostics().add_error(diag::System::Transform,
"missing transform data for SingleEntryPoint");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }
@ -51,8 +52,9 @@ Output SingleEntryPoint::Run(const Program* in, const DataMap& data) {
} }
} }
if (entry_point == nullptr) { if (entry_point == nullptr) {
out.Diagnostics().add_error("entry point '" + cfg->entry_point_name + out.Diagnostics().add_error(
"' not found"); diag::System::Transform,
"entry point '" + cfg->entry_point_name + "' not found");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }
@ -81,7 +83,7 @@ Output SingleEntryPoint::Run(const Program* in, const DataMap& data) {
out.AST().AddFunction(ctx.Clone(func)); out.AST().AddFunction(ctx.Clone(func));
} }
} else { } else {
TINT_UNREACHABLE(out.Diagnostics()) TINT_UNREACHABLE(Transform, out.Diagnostics())
<< "unhandled global declaration: " << decl->TypeInfo().name; << "unhandled global declaration: " << decl->TypeInfo().name;
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }

View File

@ -134,7 +134,7 @@ ast::Type* Transform::CreateASTTypeFor(CloneContext* ctx, const sem::Type* ty) {
if (auto* s = ty->As<sem::Sampler>()) { if (auto* s = ty->As<sem::Sampler>()) {
return ctx->dst->create<ast::Sampler>(s->kind()); return ctx->dst->create<ast::Sampler>(s->kind());
} }
TINT_UNREACHABLE(ctx->dst->Diagnostics()) TINT_UNREACHABLE(Transform, ctx->dst->Diagnostics())
<< "Unhandled type: " << ty->TypeInfo().name; << "Unhandled type: " << ty->TypeInfo().name;
return nullptr; return nullptr;
} }

View File

@ -304,7 +304,8 @@ struct State {
} }
new_function_parameters.push_back(ctx.Clone(param)); new_function_parameters.push_back(ctx.Clone(param));
} else { } else {
TINT_ICE(ctx.dst->Diagnostics()) << "Invalid entry point parameter"; TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "Invalid entry point parameter";
} }
} }
@ -346,7 +347,8 @@ struct State {
} }
members_to_clone.push_back(member); members_to_clone.push_back(member);
} else { } else {
TINT_ICE(ctx.dst->Diagnostics()) << "Invalid entry point parameter"; TINT_ICE(Transform, ctx.dst->Diagnostics())
<< "Invalid entry point parameter";
} }
} }
@ -466,7 +468,8 @@ Output VertexPulling::Run(const Program* in, const DataMap& data) {
auto* func = in->AST().Functions().Find( auto* func = in->AST().Functions().Find(
in->Symbols().Get(cfg.entry_point_name), ast::PipelineStage::kVertex); in->Symbols().Get(cfg.entry_point_name), ast::PipelineStage::kVertex);
if (func == nullptr) { if (func == nullptr) {
out.Diagnostics().add_error("Vertex stage entry point not found"); out.Diagnostics().add_error(diag::System::Transform,
"Vertex stage entry point not found");
return Output(Program(std::move(out))); return Output(Program(std::move(out)));
} }

View File

@ -78,7 +78,7 @@ struct ZeroInitWorkgroupMemory::State {
return; return;
} }
TINT_UNREACHABLE(ctx.dst->Diagnostics()) TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
<< "could not zero workgroup type: " << ty->type_name(); << "could not zero workgroup type: " << ty->type_name();
} }

View File

@ -30,8 +30,8 @@ std::string TmpFilePath(std::string ext) {
// (when the source value exceeds the representable range) is implementation // (when the source value exceeds the representable range) is implementation
// defined. While such a large file extension is unlikely in practice, we // defined. While such a large file extension is unlikely in practice, we
// enforce this here at runtime. // enforce this here at runtime.
TINT_ASSERT(ext.length() <= TINT_ASSERT(Utils, ext.length() <=
static_cast<size_t>(std::numeric_limits<int>::max())); static_cast<size_t>(std::numeric_limits<int>::max()));
std::string name = "tint_XXXXXX" + ext; std::string name = "tint_XXXXXX" + ext;
int file = mkstemps(&name[0], static_cast<int>(ext.length())); int file = mkstemps(&name[0], static_cast<int>(ext.length()));
if (file != -1) { if (file != -1) {

View File

@ -60,8 +60,9 @@ ast::TypeConstructorExpression* AppendVector(ProgramBuilder* b,
} else if (packed_el_sem_ty->Is<sem::Bool>()) { } else if (packed_el_sem_ty->Is<sem::Bool>()) {
packed_el_ty = b->create<ast::Bool>(); packed_el_ty = b->create<ast::Bool>();
} else { } else {
TINT_UNREACHABLE(b->Diagnostics()) << "unsupported vector element type: " TINT_UNREACHABLE(Writer, b->Diagnostics())
<< packed_el_sem_ty->TypeInfo().name; << "unsupported vector element type: "
<< packed_el_sem_ty->TypeInfo().name;
} }
auto* statement = vector_sem->Stmt(); auto* statement = vector_sem->Stmt();
@ -86,7 +87,7 @@ ast::TypeConstructorExpression* AppendVector(ProgramBuilder* b,
} else if (packed_el_sem_ty->Is<sem::Bool>()) { } else if (packed_el_sem_ty->Is<sem::Bool>()) {
return b->Expr(false); return b->Expr(false);
} else { } else {
TINT_UNREACHABLE(b->Diagnostics()) TINT_UNREACHABLE(Writer, b->Diagnostics())
<< "unsupported vector element type: " << "unsupported vector element type: "
<< packed_el_sem_ty->TypeInfo().name; << packed_el_sem_ty->TypeInfo().name;
} }

View File

@ -106,7 +106,7 @@ std::string FloatToBitPreservingString(float f) {
} }
} else { } else {
// Subnormal, and not zero. // Subnormal, and not zero.
TINT_ASSERT(mantissa != 0); TINT_ASSERT(Writer, mantissa != 0);
const int kTopBit = (1 << kMantissaBits); const int kTopBit = (1 << kMantissaBits);
// Shift left until we get 1.x // Shift left until we get 1.x

View File

@ -152,7 +152,7 @@ bool GeneratorImpl::Generate(std::ostream& out) {
} }
} }
} else { } else {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "unhandled module-scope declaration: " << decl->TypeInfo().name; << "unhandled module-scope declaration: " << decl->TypeInfo().name;
return false; return false;
} }
@ -188,7 +188,8 @@ bool GeneratorImpl::EmitBitcast(std::ostream& pre,
ast::BitcastExpression* expr) { ast::BitcastExpression* expr) {
auto* type = TypeOf(expr); auto* type = TypeOf(expr);
if (!type->is_integer_scalar() && !type->is_float_scalar()) { if (!type->is_integer_scalar() && !type->is_float_scalar()) {
diagnostics_.add_error("Unable to do bitcast to type " + type->type_name()); diagnostics_.add_error(diag::System::Writer,
"Unable to do bitcast to type " + type->type_name());
return false; return false;
} }
@ -305,7 +306,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre,
case ast::BinaryOp::kLogicalAnd: case ast::BinaryOp::kLogicalAnd:
case ast::BinaryOp::kLogicalOr: { case ast::BinaryOp::kLogicalOr: {
// These are both handled above. // These are both handled above.
TINT_UNREACHABLE(diagnostics_); TINT_UNREACHABLE(Writer, diagnostics_);
return false; return false;
} }
case ast::BinaryOp::kEqual: case ast::BinaryOp::kEqual:
@ -353,7 +354,8 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre,
out << "%"; out << "%";
break; break;
case ast::BinaryOp::kNone: case ast::BinaryOp::kNone:
diagnostics_.add_error("missing binary operation type"); diagnostics_.add_error(diag::System::Writer,
"missing binary operation type");
return false; return false;
} }
out << " "; out << " ";
@ -437,7 +439,7 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
case ast::StorageClass::kStorage: case ast::StorageClass::kStorage:
return EmitStorageBufferAccess(pre, out, expr, intrinsic); return EmitStorageBufferAccess(pre, out, expr, intrinsic);
default: default:
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic storage class:" << "unsupported DecomposeMemoryAccess::Intrinsic storage class:"
<< intrinsic->storage_class; << intrinsic->storage_class;
return false; return false;
@ -493,8 +495,9 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
auto* func = builder_.AST().Functions().Find(ident->symbol()); auto* func = builder_.AST().Functions().Find(ident->symbol());
if (func == nullptr) { if (func == nullptr) {
diagnostics_.add_error("Unable to find function: " + diagnostics_.add_error(diag::System::Writer,
builder_.Symbols().NameFor(ident->symbol())); "Unable to find function: " +
builder_.Symbols().NameFor(ident->symbol()));
return false; return false;
} }
@ -610,7 +613,7 @@ bool GeneratorImpl::EmitUniformBufferAccess(
case DataType::kVec4I32: case DataType::kVec4I32:
return cast("asint", load_vec4); return cast("asint", load_vec4);
} }
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: " << "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
<< static_cast<int>(intrinsic->type); << static_cast<int>(intrinsic->type);
return false; return false;
@ -618,7 +621,7 @@ bool GeneratorImpl::EmitUniformBufferAccess(
default: default:
break; break;
} }
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::Op: " << "unsupported DecomposeMemoryAccess::Intrinsic::Op: "
<< static_cast<int>(intrinsic->op); << static_cast<int>(intrinsic->op);
return false; return false;
@ -681,7 +684,7 @@ bool GeneratorImpl::EmitStorageBufferAccess(
case DataType::kVec4I32: case DataType::kVec4I32:
return load("asint", 4); return load("asint", 4);
} }
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: " << "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
<< static_cast<int>(intrinsic->type); << static_cast<int>(intrinsic->type);
return false; return false;
@ -733,7 +736,7 @@ bool GeneratorImpl::EmitStorageBufferAccess(
case DataType::kVec4I32: case DataType::kVec4I32:
return store(4); return store(4);
} }
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: " << "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
<< static_cast<int>(intrinsic->type); << static_cast<int>(intrinsic->type);
return false; return false;
@ -752,7 +755,7 @@ bool GeneratorImpl::EmitStorageBufferAccess(
return EmitStorageAtomicCall(pre, out, expr, intrinsic->op); return EmitStorageAtomicCall(pre, out, expr, intrinsic->op);
} }
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::Op: " << "unsupported DecomposeMemoryAccess::Intrinsic::Op: "
<< static_cast<int>(intrinsic->op); << static_cast<int>(intrinsic->op);
return false; return false;
@ -921,7 +924,7 @@ bool GeneratorImpl::EmitStorageAtomicCall(
break; break;
default: default:
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic DecomposeMemoryAccess::Intrinsic::Op: " << "unsupported atomic DecomposeMemoryAccess::Intrinsic::Op: "
<< static_cast<int>(op); << static_cast<int>(op);
return false; return false;
@ -1077,7 +1080,7 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre,
break; break;
default: default:
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported atomic intrinsic: " << intrinsic->Type(); << "unsupported atomic intrinsic: " << intrinsic->Type();
return false; return false;
} }
@ -1266,6 +1269,7 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre,
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing intrinsic");
return false; return false;
} }
@ -1337,6 +1341,7 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& pre,
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer,
"Internal error: unhandled data packing intrinsic"); "Internal error: unhandled data packing intrinsic");
return false; return false;
} }
@ -1354,7 +1359,7 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream&,
} else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) { } else if (intrinsic->Type() == sem::IntrinsicType::kStorageBarrier) {
out << "DeviceMemoryBarrierWithGroupSync()"; out << "DeviceMemoryBarrierWithGroupSync()";
} else { } else {
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unexpected barrier intrinsic type " << sem::str(intrinsic->Type()); << "unexpected barrier intrinsic type " << sem::str(intrinsic->Type());
return false; return false;
} }
@ -1378,7 +1383,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
auto* texture = arg(Usage::kTexture); auto* texture = arg(Usage::kTexture);
if (!texture) { if (!texture) {
TINT_ICE(diagnostics_) << "missing texture argument"; TINT_ICE(Writer, diagnostics_) << "missing texture argument";
return false; return false;
} }
@ -1398,7 +1403,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
case sem::IntrinsicType::kTextureDimensions: case sem::IntrinsicType::kTextureDimensions:
switch (texture_type->dim()) { switch (texture_type->dim()) {
case ast::TextureDimension::kNone: case ast::TextureDimension::kNone:
TINT_ICE(diagnostics_) << "texture dimension is kNone"; TINT_ICE(Writer, diagnostics_) << "texture dimension is kNone";
return false; return false;
case ast::TextureDimension::k1d: case ast::TextureDimension::k1d:
num_dimensions = 1; num_dimensions = 1;
@ -1426,7 +1431,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
case sem::IntrinsicType::kTextureNumLayers: case sem::IntrinsicType::kTextureNumLayers:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(diagnostics_) << "texture dimension is not arrayed"; TINT_ICE(Writer, diagnostics_)
<< "texture dimension is not arrayed";
return false; return false;
case ast::TextureDimension::k2dArray: case ast::TextureDimension::k2dArray:
num_dimensions = is_ms ? 4 : 3; num_dimensions = is_ms ? 4 : 3;
@ -1441,7 +1447,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
case sem::IntrinsicType::kTextureNumLevels: case sem::IntrinsicType::kTextureNumLevels:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "texture dimension does not support mips"; << "texture dimension does not support mips";
return false; return false;
case ast::TextureDimension::k2d: case ast::TextureDimension::k2d:
@ -1460,7 +1466,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
case sem::IntrinsicType::kTextureNumSamples: case sem::IntrinsicType::kTextureNumSamples:
switch (texture_type->dim()) { switch (texture_type->dim()) {
default: default:
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "texture dimension does not support multisampling"; << "texture dimension does not support multisampling";
return false; return false;
case ast::TextureDimension::k2d: case ast::TextureDimension::k2d:
@ -1474,7 +1480,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
} }
break; break;
default: default:
TINT_ICE(diagnostics_) << "unexpected intrinsic"; TINT_ICE(Writer, diagnostics_) << "unexpected intrinsic";
return false; return false;
} }
@ -1496,7 +1502,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
} }
if (num_dimensions > 4) { if (num_dimensions > 4) {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Texture query intrinsic temporary vector has " << num_dimensions << "Texture query intrinsic temporary vector has " << num_dimensions
<< " dimensions"; << " dimensions";
return false; return false;
@ -1533,7 +1539,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
} else { } else {
static constexpr char xyzw[] = {'x', 'y', 'z', 'w'}; static constexpr char xyzw[] = {'x', 'y', 'z', 'w'};
if (num_dimensions < 0 || num_dimensions > 4) { if (num_dimensions < 0 || num_dimensions > 4) {
TINT_ICE(diagnostics_) << "vector dimensions are " << num_dimensions; TINT_ICE(Writer, diagnostics_)
<< "vector dimensions are " << num_dimensions;
return false; return false;
} }
for (int i = 0; i < num_dimensions; i++) { for (int i = 0; i < num_dimensions; i++) {
@ -1593,8 +1600,9 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
break; break;
default: default:
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer,
"Internal compiler error: Unhandled texture intrinsic '" + "Internal compiler error: Unhandled texture intrinsic '" +
std::string(intrinsic->str()) + "'"); std::string(intrinsic->str()) + "'");
return false; return false;
} }
@ -1606,7 +1614,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
auto* param_coords = arg(Usage::kCoords); auto* param_coords = arg(Usage::kCoords);
if (!param_coords) { if (!param_coords) {
TINT_ICE(diagnostics_) << "missing coords argument"; TINT_ICE(Writer, diagnostics_) << "missing coords argument";
return false; return false;
} }
@ -1674,9 +1682,10 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
} }
} }
if (wgsl_ret_width > hlsl_ret_width) { if (wgsl_ret_width > hlsl_ret_width) {
TINT_ICE(diagnostics_) << "WGSL return width (" << wgsl_ret_width TINT_ICE(Writer, diagnostics_)
<< ") is wider than HLSL return width (" << "WGSL return width (" << wgsl_ret_width
<< hlsl_ret_width << ") for " << intrinsic->Type(); << ") is wider than HLSL return width (" << hlsl_ret_width << ") for "
<< intrinsic->Type();
return false; return false;
} }
} }
@ -1766,8 +1775,9 @@ std::string GeneratorImpl::generate_builtin_name(
case sem::IntrinsicType::kSmoothStep: case sem::IntrinsicType::kSmoothStep:
return "smoothstep"; return "smoothstep";
default: default:
diagnostics_.add_error("Unknown builtin method: " + diagnostics_.add_error(
std::string(intrinsic->str())); diag::System::Writer,
"Unknown builtin method: " + std::string(intrinsic->str()));
} }
return ""; return "";
@ -1936,7 +1946,8 @@ bool GeneratorImpl::EmitExpression(std::ostream& pre,
return EmitUnaryOp(pre, out, u); return EmitUnaryOp(pre, out, u);
} }
diagnostics_.add_error("unknown expression type: " + builder_.str(expr)); diagnostics_.add_error(diag::System::Writer,
"unknown expression type: " + builder_.str(expr));
return false; return false;
} }
@ -2084,7 +2095,8 @@ bool GeneratorImpl::EmitGlobalVariable(std::ostream& out,
break; break;
} }
TINT_ICE(diagnostics_) << "unhandled storage class " << sem->StorageClass(); TINT_ICE(Writer, diagnostics_)
<< "unhandled storage class " << sem->StorageClass();
return false; return false;
} }
@ -2099,7 +2111,7 @@ bool GeneratorImpl::EmitUniformVariable(std::ostream& out,
auto* str = type->As<sem::Struct>(); auto* str = type->As<sem::Struct>();
if (!str) { if (!str) {
// https://www.w3.org/TR/WGSL/#module-scope-variables // https://www.w3.org/TR/WGSL/#module-scope-variables
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "variables with uniform storage must be structure"; << "variables with uniform storage must be structure";
} }
@ -2285,7 +2297,7 @@ bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out,
if (wgsize[i].overridable_const) { if (wgsize[i].overridable_const) {
auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const); auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const);
if (!sem_const->IsPipelineConstant()) { if (!sem_const->IsPipelineConstant()) {
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "expected a pipeline-overridable constant"; << "expected a pipeline-overridable constant";
} }
out << kSpecConstantPrefix << sem_const->ConstantId(); out << kSpecConstantPrefix << sem_const->ConstantId();
@ -2310,7 +2322,8 @@ bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out,
if (!type->Is<sem::Struct>()) { if (!type->Is<sem::Struct>()) {
// ICE likely indicates that the CanonicalizeEntryPointIO transform was // ICE likely indicates that the CanonicalizeEntryPointIO transform was
// not run, or a builtin parameter was added after it was run. // not run, or a builtin parameter was added after it was run.
TINT_ICE(diagnostics_) << "Unsupported non-struct entry point parameter"; TINT_ICE(Writer, diagnostics_)
<< "Unsupported non-struct entry point parameter";
} }
if (!first) { if (!first) {
@ -2359,7 +2372,7 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
} else if (auto* ul = lit->As<ast::UintLiteral>()) { } else if (auto* ul = lit->As<ast::UintLiteral>()) {
out << ul->value() << "u"; out << ul->value() << "u";
} else { } else {
diagnostics_.add_error("unknown literal type"); diagnostics_.add_error(diag::System::Writer, "unknown literal type");
return false; return false;
} }
return true; return true;
@ -2435,8 +2448,9 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) {
} }
out << "}"; out << "}";
} else { } else {
diagnostics_.add_error("Invalid type for zero emission: " + diagnostics_.add_error(
type->type_name()); diag::System::Writer,
"Invalid type for zero emission: " + type->type_name());
return false; return false;
} }
return true; return true;
@ -2556,7 +2570,8 @@ bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) {
return EmitVariable(out, v->variable()); return EmitVariable(out, v->variable());
} }
diagnostics_.add_error("unknown statement type: " + builder_.str(stmt)); diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + builder_.str(stmt));
return false; return false;
} }
@ -2604,7 +2619,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
auto* str = type->As<sem::Struct>(); auto* str = type->As<sem::Struct>();
if (!str) { if (!str) {
// https://www.w3.org/TR/WGSL/#module-scope-variables // https://www.w3.org/TR/WGSL/#module-scope-variables
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "variables with uniform storage must be structure"; << "variables with uniform storage must be structure";
} }
auto array_length = (str->Size() + 15) / 16; auto array_length = (str->Size() + 15) / 16;
@ -2623,7 +2638,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
std::vector<uint32_t> sizes; std::vector<uint32_t> sizes;
while (auto* arr = base_type->As<sem::Array>()) { while (auto* arr = base_type->As<sem::Array>()) {
if (arr->IsRuntimeSized()) { if (arr->IsRuntimeSized()) {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Runtime arrays may only exist in storage buffers, which should " << "Runtime arrays may only exist in storage buffers, which should "
"have been transformed into a ByteAddressBuffer"; "have been transformed into a ByteAddressBuffer";
return false; return false;
@ -2662,7 +2677,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math#matrix-ordering // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math#matrix-ordering
out << mat->columns() << "x" << mat->rows(); out << mat->columns() << "x" << mat->rows();
} else if (type->Is<sem::Pointer>()) { } else if (type->Is<sem::Pointer>()) {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Attempting to emit pointer type. These should have been removed " << "Attempting to emit pointer type. These should have been removed "
"with the InlinePointerLets transform"; "with the InlinePointerLets transform";
return false; return false;
@ -2704,7 +2719,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
out << "CubeArray"; out << "CubeArray";
break; break;
default: default:
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "unexpected TextureDimension " << tex->dim(); << "unexpected TextureDimension " << tex->dim();
return false; return false;
} }
@ -2712,8 +2727,9 @@ bool GeneratorImpl::EmitType(std::ostream& out,
if (storage) { if (storage) {
auto* component = image_format_to_rwtexture_type(storage->image_format()); auto* component = image_format_to_rwtexture_type(storage->image_format());
if (component == nullptr) { if (component == nullptr) {
TINT_ICE(diagnostics_) << "Unsupported StorageTexture ImageFormat: " TINT_ICE(Writer, diagnostics_)
<< static_cast<int>(storage->image_format()); << "Unsupported StorageTexture ImageFormat: "
<< static_cast<int>(storage->image_format());
return false; return false;
} }
out << "<" << component << ">"; out << "<" << component << ">";
@ -2727,7 +2743,8 @@ bool GeneratorImpl::EmitType(std::ostream& out,
} else if (subtype->Is<sem::U32>()) { } else if (subtype->Is<sem::U32>()) {
out << "uint4"; out << "uint4";
} else { } else {
TINT_ICE(diagnostics_) << "Unsupported multisampled texture type"; TINT_ICE(Writer, diagnostics_)
<< "Unsupported multisampled texture type";
return false; return false;
} }
out << ">"; out << ">";
@ -2758,7 +2775,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
} else if (type->Is<sem::Void>()) { } else if (type->Is<sem::Void>()) {
out << "void"; out << "void";
} else { } else {
diagnostics_.add_error("unknown type in EmitType"); diagnostics_.add_error(diag::System::Writer, "unknown type in EmitType");
return false; return false;
} }
@ -2814,7 +2831,8 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
if (auto* location = deco->As<ast::LocationDecoration>()) { if (auto* location = deco->As<ast::LocationDecoration>()) {
auto& pipeline_stage_uses = str->PipelineStageUses(); auto& pipeline_stage_uses = str->PipelineStageUses();
if (pipeline_stage_uses.size() != 1) { if (pipeline_stage_uses.size() != 1) {
TINT_ICE(diagnostics_) << "invalid entry point IO struct uses"; TINT_ICE(Writer, diagnostics_)
<< "invalid entry point IO struct uses";
} }
if (pipeline_stage_uses.count(sem::PipelineStageUsage::kVertexInput)) { if (pipeline_stage_uses.count(sem::PipelineStageUsage::kVertexInput)) {
@ -2829,12 +2847,13 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) {
sem::PipelineStageUsage::kFragmentOutput)) { sem::PipelineStageUsage::kFragmentOutput)) {
out << " : SV_Target" + std::to_string(location->value()); out << " : SV_Target" + std::to_string(location->value());
} else { } else {
TINT_ICE(diagnostics_) << "invalid use of location decoration"; TINT_ICE(Writer, diagnostics_)
<< "invalid use of location decoration";
} }
} else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
auto attr = builtin_to_attribute(builtin->value()); auto attr = builtin_to_attribute(builtin->value());
if (attr.empty()) { if (attr.empty()) {
diagnostics_.add_error("unsupported builtin"); diagnostics_.add_error(diag::System::Writer, "unsupported builtin");
return false; return false;
} }
out << " : " << attr; out << " : " << attr;
@ -2888,7 +2907,8 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) {
// TODO(dsinclair): Handle variable decorations // TODO(dsinclair): Handle variable decorations
if (!var->decorations().empty()) { if (!var->decorations().empty()) {
diagnostics_.add_error("Variable decorations are not handled yet"); diagnostics_.add_error(diag::System::Writer,
"Variable decorations are not handled yet");
return false; return false;
} }
@ -2925,12 +2945,13 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out,
for (auto* d : var->decorations()) { for (auto* d : var->decorations()) {
if (!d->Is<ast::OverrideDecoration>()) { if (!d->Is<ast::OverrideDecoration>()) {
diagnostics_.add_error("Decorated const values not valid"); diagnostics_.add_error(diag::System::Writer,
"Decorated const values not valid");
return false; return false;
} }
} }
if (!var->is_const()) { if (!var->is_const()) {
diagnostics_.add_error("Expected a const value"); diagnostics_.add_error(diag::System::Writer, "Expected a const value");
return false; return false;
} }

View File

@ -101,7 +101,7 @@ bool GeneratorImpl::Generate() {
case ast::StorageClass::kPrivate: case ast::StorageClass::kPrivate:
case ast::StorageClass::kWorkgroup: case ast::StorageClass::kWorkgroup:
// These are pushed into the entry point by the sanitizer. // These are pushed into the entry point by the sanitizer.
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "module-scope variables in the private/workgroup storage " << "module-scope variables in the private/workgroup storage "
"class should have been handled by the MSL sanitizer"; "class should have been handled by the MSL sanitizer";
break; break;
@ -134,7 +134,8 @@ bool GeneratorImpl::EmitTypeDecl(const sem::Type* ty) {
return false; return false;
} }
} else { } else {
diagnostics_.add_error("unknown alias type: " + ty->type_name()); diagnostics_.add_error(diag::System::Writer,
"unknown alias type: " + ty->type_name());
return false; return false;
} }
@ -269,7 +270,8 @@ bool GeneratorImpl::EmitBinary(ast::BinaryExpression* expr) {
out_ << "%"; out_ << "%";
break; break;
case ast::BinaryOp::kNone: case ast::BinaryOp::kNone:
diagnostics_.add_error("missing binary operation type"); diagnostics_.add_error(diag::System::Writer,
"missing binary operation type");
return false; return false;
} }
out_ << " "; out_ << " ";
@ -297,8 +299,9 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) {
auto* func = program_->AST().Functions().Find(ident->symbol()); auto* func = program_->AST().Functions().Find(ident->symbol());
if (func == nullptr) { if (func == nullptr) {
diagnostics_.add_error("Unable to find function: " + diagnostics_.add_error(diag::System::Writer,
program_->Symbols().NameFor(ident->symbol())); "Unable to find function: " +
program_->Symbols().NameFor(ident->symbol()));
return false; return false;
} }
@ -425,7 +428,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr,
auto* texture = arg(Usage::kTexture); auto* texture = arg(Usage::kTexture);
if (!texture) { if (!texture) {
TINT_ICE(diagnostics_) << "missing texture arg"; TINT_ICE(Writer, diagnostics_) << "missing texture arg";
return false; return false;
} }
@ -457,7 +460,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr,
std::vector<const char*> dims; std::vector<const char*> dims;
switch (texture_type->dim()) { switch (texture_type->dim()) {
case ast::TextureDimension::kNone: case ast::TextureDimension::kNone:
diagnostics_.add_error("texture dimension is kNone"); diagnostics_.add_error(diag::System::Writer,
"texture dimension is kNone");
return false; return false;
case ast::TextureDimension::k1d: case ast::TextureDimension::k1d:
dims = {"width"}; dims = {"width"};
@ -557,7 +561,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr,
out_ << ".write("; out_ << ".write(";
break; break;
default: default:
TINT_UNREACHABLE(diagnostics_) TINT_UNREACHABLE(Writer, diagnostics_)
<< "Unhandled texture intrinsic '" << intrinsic->str() << "'"; << "Unhandled texture intrinsic '" << intrinsic->str() << "'";
return false; return false;
} }
@ -595,7 +599,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr,
out_ << "uint3("; out_ << "uint3(";
break; break;
default: default:
TINT_ICE(diagnostics_) << "unhandled texture dimensionality"; TINT_ICE(Writer, diagnostics_)
<< "unhandled texture dimensionality";
break; break;
} }
} }
@ -653,7 +658,7 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr,
default: { default: {
std::stringstream err; std::stringstream err;
err << "MSL does not support gradients for " << dim << " textures"; err << "MSL does not support gradients for " << dim << " textures";
diagnostics_.add_error(err.str()); diagnostics_.add_error(diag::System::Writer, err.str());
return false; return false;
} }
} }
@ -813,8 +818,9 @@ std::string GeneratorImpl::generate_builtin_name(
out += "unpack_unorm2x16_to_float"; out += "unpack_unorm2x16_to_float";
break; break;
default: default:
diagnostics_.add_error("Unknown import method: " + diagnostics_.add_error(
std::string(intrinsic->str())); diag::System::Writer,
"Unknown import method: " + std::string(intrinsic->str()));
return ""; return "";
} }
return out; return out;
@ -949,8 +955,9 @@ bool GeneratorImpl::EmitZeroValue(const sem::Type* type) {
} else if (type->As<sem::Struct>()) { } else if (type->As<sem::Struct>()) {
out_ << "{}"; out_ << "{}";
} else { } else {
diagnostics_.add_error("Invalid type for zero emission: " + diagnostics_.add_error(
type->type_name()); diag::System::Writer,
"Invalid type for zero emission: " + type->type_name());
return false; return false;
} }
return true; return true;
@ -971,7 +978,7 @@ bool GeneratorImpl::EmitLiteral(ast::Literal* lit) {
} else if (auto* ul = lit->As<ast::UintLiteral>()) { } else if (auto* ul = lit->As<ast::UintLiteral>()) {
out_ << ul->value() << "u"; out_ << ul->value() << "u";
} else { } else {
diagnostics_.add_error("unknown literal type"); diagnostics_.add_error(diag::System::Writer, "unknown literal type");
return false; return false;
} }
return true; return true;
@ -1003,7 +1010,8 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
return EmitUnaryOp(u); return EmitUnaryOp(u);
} }
diagnostics_.add_error("unknown expression type: " + program_->str(expr)); diagnostics_.add_error(diag::System::Writer,
"unknown expression type: " + program_->str(expr));
return false; return false;
} }
@ -1159,7 +1167,7 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
auto* binding = auto* binding =
ast::GetDecoration<ast::BindingDecoration>(var->decorations()); ast::GetDecoration<ast::BindingDecoration>(var->decorations());
if (binding == nullptr) { if (binding == nullptr) {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "missing binding attribute for entry point parameter"; << "missing binding attribute for entry point parameter";
return false; return false;
} }
@ -1168,7 +1176,8 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
} else if (var->type()->Is<ast::Texture>()) { } else if (var->type()->Is<ast::Texture>()) {
out_ << " [[texture(" << binding->value() << ")]]"; out_ << " [[texture(" << binding->value() << ")]]";
} else { } else {
TINT_ICE(diagnostics_) << "invalid handle type entry point parameter"; TINT_ICE(Writer, diagnostics_)
<< "invalid handle type entry point parameter";
return false; return false;
} }
} else { } else {
@ -1184,13 +1193,13 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
auto attr = builtin_to_attribute(builtin->value()); auto attr = builtin_to_attribute(builtin->value());
if (attr.empty()) { if (attr.empty()) {
diagnostics_.add_error("unknown builtin"); diagnostics_.add_error(diag::System::Writer, "unknown builtin");
return false; return false;
} }
out_ << " [[" << attr << "]]"; out_ << " [[" << attr << "]]";
} }
if (!builtin_found) { if (!builtin_found) {
TINT_ICE(diagnostics_) << "Unsupported entry point parameter"; TINT_ICE(Writer, diagnostics_) << "Unsupported entry point parameter";
} }
} }
} }
@ -1208,8 +1217,9 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
auto* binding = data.second.binding; auto* binding = data.second.binding;
if (binding == nullptr) { if (binding == nullptr) {
diagnostics_.add_error( diagnostics_.add_error(
diag::System::Writer,
"unable to find binding information for uniform: " + "unable to find binding information for uniform: " +
program_->Symbols().NameFor(var->Declaration()->symbol())); program_->Symbols().NameFor(var->Declaration()->symbol()));
return false; return false;
} }
// auto* set = data.second.set; // auto* set = data.second.set;
@ -1472,7 +1482,8 @@ bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
return EmitVariable(var); return EmitVariable(var);
} }
diagnostics_.add_error("unknown statement type: " + program_->str(stmt)); diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + program_->str(stmt));
return false; return false;
} }
@ -1549,7 +1560,7 @@ bool GeneratorImpl::EmitType(const sem::Type* type, const std::string& name) {
out_ << "constant "; out_ << "constant ";
break; break;
default: default:
TINT_ICE(diagnostics_) << "unhandled storage class for pointer"; TINT_ICE(Writer, diagnostics_) << "unhandled storage class for pointer";
} }
if (ptr->StoreType()->Is<sem::Array>()) { if (ptr->StoreType()->Is<sem::Array>()) {
std::string inner = "(*" + name + ")"; std::string inner = "(*" + name + ")";
@ -1595,7 +1606,8 @@ bool GeneratorImpl::EmitType(const sem::Type* type, const std::string& name) {
out_ << "cube_array"; out_ << "cube_array";
break; break;
default: default:
diagnostics_.add_error("Invalid texture dimensions"); diagnostics_.add_error(diag::System::Writer,
"Invalid texture dimensions");
return false; return false;
} }
if (tex->Is<sem::MultisampledTexture>()) { if (tex->Is<sem::MultisampledTexture>()) {
@ -1615,7 +1627,8 @@ bool GeneratorImpl::EmitType(const sem::Type* type, const std::string& name) {
} else if (storage->access() == ast::Access::kWrite) { } else if (storage->access() == ast::Access::kWrite) {
out_ << ", access::write"; out_ << ", access::write";
} else { } else {
diagnostics_.add_error("Invalid access control for storage texture"); diagnostics_.add_error(diag::System::Writer,
"Invalid access control for storage texture");
return false; return false;
} }
} else if (auto* ms = tex->As<sem::MultisampledTexture>()) { } else if (auto* ms = tex->As<sem::MultisampledTexture>()) {
@ -1629,7 +1642,7 @@ bool GeneratorImpl::EmitType(const sem::Type* type, const std::string& name) {
} }
out_ << ", access::sample"; out_ << ", access::sample";
} else { } else {
diagnostics_.add_error("invalid texture type"); diagnostics_.add_error(diag::System::Writer, "invalid texture type");
return false; return false;
} }
out_ << ">"; out_ << ">";
@ -1644,7 +1657,8 @@ bool GeneratorImpl::EmitType(const sem::Type* type, const std::string& name) {
} else if (type->Is<sem::Void>()) { } else if (type->Is<sem::Void>()) {
out_ << "void"; out_ << "void";
} else { } else {
diagnostics_.add_error("unknown type in EmitType: " + type->type_name()); diagnostics_.add_error(diag::System::Writer,
"unknown type in EmitType: " + type->type_name());
return false; return false;
} }
@ -1700,7 +1714,7 @@ bool GeneratorImpl::EmitStructType(const sem::Struct* str) {
if (is_host_shareable) { if (is_host_shareable) {
if (wgsl_offset < msl_offset) { if (wgsl_offset < msl_offset) {
// Unimplementable layout // Unimplementable layout
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Structure member WGSL offset (" << wgsl_offset << "Structure member WGSL offset (" << wgsl_offset
<< ") is behind MSL offset (" << msl_offset << ")"; << ") is behind MSL offset (" << msl_offset << ")";
return false; return false;
@ -1737,14 +1751,15 @@ bool GeneratorImpl::EmitStructType(const sem::Struct* str) {
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
auto attr = builtin_to_attribute(builtin->value()); auto attr = builtin_to_attribute(builtin->value());
if (attr.empty()) { if (attr.empty()) {
diagnostics_.add_error("unknown builtin"); diagnostics_.add_error(diag::System::Writer, "unknown builtin");
return false; return false;
} }
out_ << " [[" << attr << "]]"; out_ << " [[" << attr << "]]";
} else if (auto* loc = deco->As<ast::LocationDecoration>()) { } else if (auto* loc = deco->As<ast::LocationDecoration>()) {
auto& pipeline_stage_uses = str->PipelineStageUses(); auto& pipeline_stage_uses = str->PipelineStageUses();
if (pipeline_stage_uses.size() != 1) { if (pipeline_stage_uses.size() != 1) {
TINT_ICE(diagnostics_) << "invalid entry point IO struct uses"; TINT_ICE(Writer, diagnostics_)
<< "invalid entry point IO struct uses";
} }
if (pipeline_stage_uses.count(sem::PipelineStageUsage::kVertexInput)) { if (pipeline_stage_uses.count(sem::PipelineStageUsage::kVertexInput)) {
@ -1759,7 +1774,8 @@ bool GeneratorImpl::EmitStructType(const sem::Struct* str) {
sem::PipelineStageUsage::kFragmentOutput)) { sem::PipelineStageUsage::kFragmentOutput)) {
out_ << " [[color(" + std::to_string(loc->value()) + ")]]"; out_ << " [[color(" + std::to_string(loc->value()) + ")]]";
} else { } else {
TINT_ICE(diagnostics_) << "invalid use of location decoration"; TINT_ICE(Writer, diagnostics_)
<< "invalid use of location decoration";
} }
} }
} }
@ -1770,7 +1786,7 @@ bool GeneratorImpl::EmitStructType(const sem::Struct* str) {
// Calculate new MSL offset // Calculate new MSL offset
auto size_align = MslPackedTypeSizeAndAlign(ty); auto size_align = MslPackedTypeSizeAndAlign(ty);
if (msl_offset % size_align.align) { if (msl_offset % size_align.align) {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Misaligned MSL structure member " << "Misaligned MSL structure member "
<< ty->FriendlyName(program_->Symbols()) << " " << name; << ty->FriendlyName(program_->Symbols()) << " " << name;
return false; return false;
@ -1828,7 +1844,7 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var) {
for (auto* deco : decl->decorations()) { for (auto* deco : decl->decorations()) {
if (!deco->Is<ast::InternalDecoration>()) { if (!deco->Is<ast::InternalDecoration>()) {
TINT_ICE(diagnostics_) << "unexpected variable decoration"; TINT_ICE(Writer, diagnostics_) << "unexpected variable decoration";
return false; return false;
} }
} }
@ -1845,7 +1861,7 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var) {
out_ << "threadgroup "; out_ << "threadgroup ";
break; break;
default: default:
TINT_ICE(diagnostics_) << "unhandled variable storage class"; TINT_ICE(Writer, diagnostics_) << "unhandled variable storage class";
return false; return false;
} }
@ -1886,12 +1902,13 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
for (auto* d : var->decorations()) { for (auto* d : var->decorations()) {
if (!d->Is<ast::OverrideDecoration>()) { if (!d->Is<ast::OverrideDecoration>()) {
diagnostics_.add_error("Decorated const values not valid"); diagnostics_.add_error(diag::System::Writer,
"Decorated const values not valid");
return false; return false;
} }
} }
if (!var->is_const()) { if (!var->is_const()) {
diagnostics_.add_error("Expected a const value"); diagnostics_.add_error(diag::System::Writer, "Expected a const value");
return false; return false;
} }
@ -1963,8 +1980,9 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(
if (auto* arr = ty->As<sem::Array>()) { if (auto* arr = ty->As<sem::Array>()) {
if (!arr->IsStrideImplicit()) { if (!arr->IsStrideImplicit()) {
TINT_ICE(diagnostics_) << "arrays with explicit strides should have " TINT_ICE(Writer, diagnostics_)
"removed with the PadArrayElements transform"; << "arrays with explicit strides should have "
"removed with the PadArrayElements transform";
return {}; return {};
} }
auto num_els = std::max<uint32_t>(arr->Count(), 1); auto num_els = std::max<uint32_t>(arr->Count(), 1);
@ -1977,7 +1995,8 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(
return SizeAndAlign{str->Size(), str->Align()}; return SizeAndAlign{str->Size(), str->Align()};
} }
TINT_UNREACHABLE(diagnostics_) << "Unhandled type " << ty->TypeInfo().name; TINT_UNREACHABLE(Writer, diagnostics_)
<< "Unhandled type " << ty->TypeInfo().name;
return {}; return {};
} }

View File

@ -453,7 +453,7 @@ bool Builder::GenerateExecutionModes(ast::Function* func, uint32_t id) {
if (has_overridable_workgroup_size_) { if (has_overridable_workgroup_size_) {
// Only one stage can have a pipeline-overridable workgroup size. // Only one stage can have a pipeline-overridable workgroup size.
// TODO(crbug.com/tint/810): Use LocalSizeId to handle this scenario. // TODO(crbug.com/tint/810): Use LocalSizeId to handle this scenario.
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "multiple stages using pipeline-overridable workgroup sizes"; << "multiple stages using pipeline-overridable workgroup sizes";
} }
has_overridable_workgroup_size_ = true; has_overridable_workgroup_size_ = true;
@ -477,7 +477,7 @@ bool Builder::GenerateExecutionModes(ast::Function* func, uint32_t id) {
// Make the constant specializable. // Make the constant specializable.
auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const); auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const);
if (!sem_const->IsPipelineConstant()) { if (!sem_const->IsPipelineConstant()) {
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "expected a pipeline-overridable constant"; << "expected a pipeline-overridable constant";
} }
constant.is_spec_op = true; constant.is_spec_op = true;
@ -885,7 +885,8 @@ bool Builder::GenerateArrayAccessor(ast::ArrayAccessorExpression* expr,
if (auto* scalar = expr->idx_expr()->As<ast::ScalarConstructorExpression>()) { if (auto* scalar = expr->idx_expr()->As<ast::ScalarConstructorExpression>()) {
auto* literal = scalar->literal()->As<ast::IntLiteral>(); auto* literal = scalar->literal()->As<ast::IntLiteral>();
if (!literal) { if (!literal) {
TINT_ICE(builder_.Diagnostics()) << "bad literal in array accessor"; TINT_ICE(Writer, builder_.Diagnostics())
<< "bad literal in array accessor";
return false; return false;
} }
@ -917,7 +918,8 @@ bool Builder::GenerateArrayAccessor(ast::ArrayAccessorExpression* expr,
return true; return true;
} }
TINT_ICE(builder_.Diagnostics()) << "unsupported array accessor expression"; TINT_ICE(Writer, builder_.Diagnostics())
<< "unsupported array accessor expression";
return false; return false;
} }
@ -1042,7 +1044,7 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr,
return true; return true;
} }
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "unhandled member index type: " << expr_sem->TypeInfo().name; << "unhandled member index type: " << expr_sem->TypeInfo().name;
return false; return false;
} }
@ -1050,7 +1052,7 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr,
uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) { uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) {
if (!expr->IsAnyOf<ast::ArrayAccessorExpression, if (!expr->IsAnyOf<ast::ArrayAccessorExpression,
ast::MemberAccessorExpression>()) { ast::MemberAccessorExpression>()) {
TINT_ICE(builder_.Diagnostics()) << "expression is not an accessor"; TINT_ICE(Writer, builder_.Diagnostics()) << "expression is not an accessor";
return 0; return 0;
} }
@ -1466,7 +1468,7 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
// This should not happen as we rely on constant folding to obviate // This should not happen as we rely on constant folding to obviate
// casts/conversions for module-scope variables // casts/conversions for module-scope variables
if (is_global_init) { if (is_global_init) {
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "Module-level conversions are not supported. Conversions should " << "Module-level conversions are not supported. Conversions should "
"have already been constant-folded by the FoldConstants transform."; "have already been constant-folded by the FoldConstants transform.";
return 0; return 0;
@ -1545,7 +1547,7 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
return result_id; return result_id;
} else { } else {
TINT_ICE(builder_.Diagnostics()) << "Invalid from_type"; TINT_ICE(Writer, builder_.Diagnostics()) << "Invalid from_type";
} }
if (op == spv::Op::OpNop) { if (op == spv::Op::OpNop) {
@ -2506,7 +2508,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
auto gen_arg = [&](Usage usage) { auto gen_arg = [&](Usage usage) {
auto* argument = arg(usage); auto* argument = arg(usage);
if (!argument) { if (!argument) {
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "missing argument " << static_cast<int>(usage); << "missing argument " << static_cast<int>(usage);
} }
return gen(argument); return gen(argument);
@ -2514,7 +2516,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
auto* texture = arg(Usage::kTexture); auto* texture = arg(Usage::kTexture);
if (!texture) { if (!texture) {
TINT_ICE(builder_.Diagnostics()) << "missing texture argument"; TINT_ICE(Writer, builder_.Diagnostics()) << "missing texture argument";
} }
auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>(); auto* texture_type = TypeOf(texture)->UnwrapRef()->As<sem::Texture>();
@ -2845,7 +2847,7 @@ bool Builder::GenerateTextureIntrinsic(ast::CallExpression* call,
break; break;
} }
default: default:
TINT_UNREACHABLE(builder_.Diagnostics()); TINT_UNREACHABLE(Writer, builder_.Diagnostics());
return false; return false;
} }
@ -2942,7 +2944,7 @@ bool Builder::GenerateAtomicIntrinsic(ast::CallExpression* call,
ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Device))); ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Device)));
break; break;
default: default:
TINT_UNREACHABLE(builder_.Diagnostics()) TINT_UNREACHABLE(Writer, builder_.Diagnostics())
<< "unhandled atomic storage class " << storage_class; << "unhandled atomic storage class " << storage_class;
return false; return false;
} }
@ -3115,7 +3117,7 @@ bool Builder::GenerateAtomicIntrinsic(ast::CallExpression* call,
zero = GenerateConstantIfNeeded(ScalarConstant::U32(0u)); zero = GenerateConstantIfNeeded(ScalarConstant::U32(0u));
one = GenerateConstantIfNeeded(ScalarConstant::U32(1u)); one = GenerateConstantIfNeeded(ScalarConstant::U32(1u));
} else { } else {
TINT_UNREACHABLE(builder_.Diagnostics()) TINT_UNREACHABLE(Writer, builder_.Diagnostics())
<< "unsupported atomic type " << value_sem_type->TypeInfo().name; << "unsupported atomic type " << value_sem_type->TypeInfo().name;
} }
if (zero == 0 || one == 0) { if (zero == 0 || one == 0) {
@ -3144,7 +3146,7 @@ bool Builder::GenerateAtomicIntrinsic(ast::CallExpression* call,
}); });
} }
default: default:
TINT_UNREACHABLE(builder_.Diagnostics()) TINT_UNREACHABLE(Writer, builder_.Diagnostics())
<< "unhandled atomic intrinsic " << intrinsic->Type(); << "unhandled atomic intrinsic " << intrinsic->Type();
return false; return false;
} }
@ -3374,7 +3376,7 @@ bool Builder::GenerateSwitchStatement(ast::SwitchStatement* stmt) {
if (LastIsFallthrough(item->body())) { if (LastIsFallthrough(item->body())) {
if (i == (body.size() - 1)) { if (i == (body.size() - 1)) {
// This case is caught by Resolver validation // This case is caught by Resolver validation
TINT_UNREACHABLE(builder_.Diagnostics()); TINT_UNREACHABLE(Writer, builder_.Diagnostics());
return false; return false;
} }
if (!push_function_inst(spv::Op::OpBranch, if (!push_function_inst(spv::Op::OpBranch,
@ -3938,7 +3940,8 @@ SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin,
} else if (storage == ast::StorageClass::kOutput) { } else if (storage == ast::StorageClass::kOutput) {
return SpvBuiltInPosition; return SpvBuiltInPosition;
} else { } else {
TINT_ICE(builder_.Diagnostics()) << "invalid storage class for builtin"; TINT_ICE(Writer, builder_.Diagnostics())
<< "invalid storage class for builtin";
break; break;
} }
case ast::Builtin::kVertexIndex: case ast::Builtin::kVertexIndex:

View File

@ -192,7 +192,7 @@ class Builder {
/// @param operands the variable operands /// @param operands the variable operands
void push_function_var(const OperandList& operands) { void push_function_var(const OperandList& operands) {
if (functions_.empty()) { if (functions_.empty()) {
TINT_ICE(builder_.Diagnostics()) TINT_ICE(Writer, builder_.Diagnostics())
<< "push_function_var() called without a function"; << "push_function_var() called without a function";
} }
functions_.back().push_var(operands); functions_.back().push_var(operands);

View File

@ -80,7 +80,7 @@ bool GeneratorImpl::Generate() {
return false; return false;
} }
} else { } else {
TINT_UNREACHABLE(diagnostics_); TINT_UNREACHABLE(Writer, diagnostics_);
return false; return false;
} }
@ -106,8 +106,9 @@ bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) {
return false; return false;
} }
} else { } else {
diagnostics_.add_error("unknown declared type: " + diagnostics_.add_error(
std::string(ty->TypeInfo().name)); diag::System::Writer,
"unknown declared type: " + std::string(ty->TypeInfo().name));
return false; return false;
} }
return true; return true;
@ -139,7 +140,7 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
return EmitUnaryOp(u); return EmitUnaryOp(u);
} }
diagnostics_.add_error("unknown expression type"); diagnostics_.add_error(diag::System::Writer, "unknown expression type");
return false; return false;
} }
@ -273,7 +274,7 @@ bool GeneratorImpl::EmitLiteral(ast::Literal* lit) {
} else if (auto* ul = lit->As<ast::UintLiteral>()) { } else if (auto* ul = lit->As<ast::UintLiteral>()) {
out_ << ul->value() << "u"; out_ << ul->value() << "u";
} else { } else {
diagnostics_.add_error("unknown literal type"); diagnostics_.add_error(diag::System::Writer, "unknown literal type");
return false; return false;
} }
return true; return true;
@ -349,7 +350,7 @@ bool GeneratorImpl::EmitFunction(ast::Function* func) {
bool GeneratorImpl::EmitImageFormat(const ast::ImageFormat fmt) { bool GeneratorImpl::EmitImageFormat(const ast::ImageFormat fmt) {
switch (fmt) { switch (fmt) {
case ast::ImageFormat::kNone: case ast::ImageFormat::kNone:
diagnostics_.add_error("unknown image format"); diagnostics_.add_error(diag::System::Writer, "unknown image format");
return false; return false;
default: default:
out_ << fmt; out_ << fmt;
@ -371,7 +372,7 @@ bool GeneratorImpl::EmitAccess(const ast::Access access) {
default: default:
break; break;
} }
diagnostics_.add_error("unknown access"); diagnostics_.add_error(diag::System::Writer, "unknown access");
return false; return false;
} }
@ -435,7 +436,7 @@ bool GeneratorImpl::EmitType(const ast::Type* ty) {
} else if (texture->Is<ast::StorageTexture>()) { } else if (texture->Is<ast::StorageTexture>()) {
out_ << "storage_"; out_ << "storage_";
} else { } else {
diagnostics_.add_error("unknown texture type"); diagnostics_.add_error(diag::System::Writer, "unknown texture type");
return false; return false;
} }
@ -459,7 +460,8 @@ bool GeneratorImpl::EmitType(const ast::Type* ty) {
out_ << "cube_array"; out_ << "cube_array";
break; break;
default: default:
diagnostics_.add_error("unknown texture dimension"); diagnostics_.add_error(diag::System::Writer,
"unknown texture dimension");
return false; return false;
} }
@ -500,7 +502,8 @@ bool GeneratorImpl::EmitType(const ast::Type* ty) {
} else if (auto* tn = ty->As<ast::TypeName>()) { } else if (auto* tn = ty->As<ast::TypeName>()) {
out_ << program_->Symbols().NameFor(tn->name()); out_ << program_->Symbols().NameFor(tn->name());
} else { } else {
diagnostics_.add_error("unknown type in EmitType: " + ty->type_name()); diagnostics_.add_error(diag::System::Writer,
"unknown type in EmitType: " + ty->type_name());
return false; return false;
} }
return true; return true;
@ -647,7 +650,8 @@ bool GeneratorImpl::EmitDecorations(const ast::DecorationList& decos) {
return false; return false;
} }
} else { } else {
TINT_ICE(diagnostics_) << "Unsupported workgroup_size expression"; TINT_ICE(Writer, diagnostics_)
<< "Unsupported workgroup_size expression";
} }
} }
} }
@ -676,7 +680,7 @@ bool GeneratorImpl::EmitDecorations(const ast::DecorationList& decos) {
} else if (auto* internal = deco->As<ast::InternalDecoration>()) { } else if (auto* internal = deco->As<ast::InternalDecoration>()) {
out_ << "internal(" << internal->InternalName() << ")"; out_ << "internal(" << internal->InternalName() << ")";
} else { } else {
TINT_ICE(diagnostics_) TINT_ICE(Writer, diagnostics_)
<< "Unsupported decoration '" << deco->TypeInfo().name << "'"; << "Unsupported decoration '" << deco->TypeInfo().name << "'";
return false; return false;
} }
@ -750,7 +754,8 @@ bool GeneratorImpl::EmitBinary(ast::BinaryExpression* expr) {
out_ << "%"; out_ << "%";
break; break;
case ast::BinaryOp::kNone: case ast::BinaryOp::kNone:
diagnostics_.add_error("missing binary operation type"); diagnostics_.add_error(diag::System::Writer,
"missing binary operation type");
return false; return false;
} }
out_ << " "; out_ << " ";
@ -870,7 +875,8 @@ bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
return EmitVariable(v->variable()); return EmitVariable(v->variable());
} }
diagnostics_.add_error("unknown statement type: " + program_->str(stmt)); diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + program_->str(stmt));
return false; return false;
} }
@ -1059,7 +1065,8 @@ std::string GeneratorImpl::UniqueIdentifier(const std::string& suffix) {
return ident; return ident;
} }
} }
diagnostics_.add_error("Unable to generate a unique WGSL identifier"); diagnostics_.add_error(diag::System::Writer,
"Unable to generate a unique WGSL identifier");
return "<invalid-ident>"; return "<invalid-ident>";
} }