[ir] Add an IR option into the ICE machinery.
This CL adds a `TINT_IR_ICE` which takes the IR module and dumps the
disassembly before the ICE error message.
Bug: tint:1718
Change-Id: Ibcfc5acb97704acec36ae5c537af4869832c428a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/161760
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/core/ir/BUILD.bazel b/src/tint/lang/core/ir/BUILD.bazel
index a07a52e..3c62fe9 100644
--- a/src/tint/lang/core/ir/BUILD.bazel
+++ b/src/tint/lang/core/ir/BUILD.bazel
@@ -113,6 +113,7 @@
"exit_switch.h",
"function.h",
"function_param.h",
+ "ice.h",
"if.h",
"instruction.h",
"instruction_result.h",
diff --git a/src/tint/lang/core/ir/BUILD.cmake b/src/tint/lang/core/ir/BUILD.cmake
index 028790d..19c6a8a 100644
--- a/src/tint/lang/core/ir/BUILD.cmake
+++ b/src/tint/lang/core/ir/BUILD.cmake
@@ -89,6 +89,7 @@
lang/core/ir/function.h
lang/core/ir/function_param.cc
lang/core/ir/function_param.h
+ lang/core/ir/ice.h
lang/core/ir/if.cc
lang/core/ir/if.h
lang/core/ir/instruction.cc
diff --git a/src/tint/lang/core/ir/BUILD.gn b/src/tint/lang/core/ir/BUILD.gn
index 0e76537..9bcb139 100644
--- a/src/tint/lang/core/ir/BUILD.gn
+++ b/src/tint/lang/core/ir/BUILD.gn
@@ -92,6 +92,7 @@
"function.h",
"function_param.cc",
"function_param.h",
+ "ice.h",
"if.cc",
"if.h",
"instruction.cc",
diff --git a/src/tint/lang/core/ir/ice.h b/src/tint/lang/core/ir/ice.h
new file mode 100644
index 0000000..40ef1dd
--- /dev/null
+++ b/src/tint/lang/core/ir/ice.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_CORE_IR_ICE_H_
+#define SRC_TINT_LANG_CORE_IR_ICE_H_
+
+#include "src/tint/lang/core/ir/disassembler.h"
+
+/// Emit an ICE message with the disassembly of `mod` attached.
+#define TINT_IR_ICE(mod) TINT_ICE() << tint::core::ir::Disassembler{mod}.Disassemble() << "\n"
+
+#endif // SRC_TINT_LANG_CORE_IR_ICE_H_
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index 8ac6017..c003776 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -38,6 +38,7 @@
#include "src/tint/lang/core/ir/constant.h"
#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
+#include "src/tint/lang/core/ir/ice.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
@@ -332,7 +333,7 @@
out << "threadgroup ";
break;
default:
- TINT_ICE() << "unhandled variable address space";
+ TINT_IR_ICE(ir_) << "unhandled variable address space";
return;
}
@@ -451,7 +452,7 @@
out << "constant";
break;
default:
- TINT_ICE() << "unhandled address space: " << sc;
+ TINT_IR_ICE(ir_) << "unhandled address space: " << sc;
break;
}
}
@@ -524,7 +525,7 @@
} else {
auto count = arr->ConstantCount();
if (!count) {
- TINT_ICE() << core::type::Array::kErrExpectedConstantCount;
+ TINT_IR_ICE(ir_) << core::type::Array::kErrExpectedConstantCount;
return;
}
out << count.value();
@@ -556,7 +557,7 @@
/// @param tex the texture to emit
void EmitTextureType(StringStream& out, const core::type::Texture* tex) {
if (TINT_UNLIKELY(tex->Is<core::type::ExternalTexture>())) {
- TINT_ICE() << "Multiplanar external texture transform was not run.";
+ TINT_IR_ICE(ir_) << "Multiplanar external texture transform was not run.";
return;
}
@@ -586,7 +587,7 @@
out << "cube_array";
break;
default:
- TINT_ICE() << "invalid texture dimensions";
+ TINT_IR_ICE(ir_) << "invalid texture dimensions";
return;
}
if (tex->IsAnyOf<core::type::MultisampledTexture, core::type::DepthMultisampledTexture>()) {
@@ -609,7 +610,7 @@
} else if (storage->access() == core::Access::kWrite) {
out << "access::write";
} else {
- TINT_ICE() << "invalid access control for storage texture";
+ TINT_IR_ICE(ir_) << "invalid access control for storage texture";
return;
}
},
@@ -671,8 +672,8 @@
if (is_host_shareable) {
if (TINT_UNLIKELY(ir_offset < msl_offset)) {
// Unimplementable layout
- TINT_ICE() << "Structure member offset (" << ir_offset
- << ") is behind MSL offset (" << msl_offset << ")";
+ TINT_IR_ICE(ir_) << "Structure member offset (" << ir_offset
+ << ") is behind MSL offset (" << msl_offset << ")";
return;
}
@@ -696,7 +697,7 @@
if (auto builtin = attributes.builtin) {
auto name = BuiltinToAttribute(builtin.value());
if (name.empty()) {
- TINT_ICE() << "unknown builtin";
+ TINT_IR_ICE(ir_) << "unknown builtin";
return;
}
out << " [[" << name << "]]";
@@ -705,7 +706,7 @@
if (auto location = attributes.location) {
auto& pipeline_stage_uses = str->PipelineStageUses();
if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) {
- TINT_ICE() << "invalid entry point IO struct uses";
+ TINT_IR_ICE(ir_) << "invalid entry point IO struct uses";
return;
}
@@ -721,7 +722,7 @@
core::type::PipelineStageUsage::kFragmentOutput))) {
out << " [[color(" + std::to_string(location.value()) + ")]]";
} else {
- TINT_ICE() << "invalid use of location decoration";
+ TINT_IR_ICE(ir_) << "invalid use of location decoration";
return;
}
}
@@ -729,7 +730,7 @@
if (auto interpolation = attributes.interpolation) {
auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
if (name.empty()) {
- TINT_ICE() << "unknown interpolation attribute";
+ TINT_IR_ICE(ir_) << "unknown interpolation attribute";
return;
}
out << " [[" << name << "]]";
@@ -746,9 +747,9 @@
// Calculate new MSL offset
auto size_align = MslPackedTypeSizeAndAlign(ty);
if (TINT_UNLIKELY(msl_offset % size_align.align)) {
- TINT_ICE() << "Misaligned MSL structure member " << mem_name << " : "
- << ty->FriendlyName() << " offset: " << msl_offset
- << " align: " << size_align.align;
+ TINT_IR_ICE(ir_) << "Misaligned MSL structure member " << mem_name << " : "
+ << ty->FriendlyName() << " offset: " << msl_offset
+ << " align: " << size_align.align;
return;
}
msl_offset += size_align.size;
@@ -816,7 +817,7 @@
auto count = a->ConstantCount();
if (!count) {
- TINT_ICE() << core::type::Array::kErrExpectedConstantCount;
+ TINT_IR_ICE(ir_) << core::type::Array::kErrExpectedConstantCount;
return;
}
emit_values(*count);
@@ -903,8 +904,8 @@
[&](Default) -> ExprAndPtrKind {
auto lookup = bindings_.Find(value);
if (TINT_UNLIKELY(!lookup)) {
- TINT_ICE() << "Expr(" << (value ? value->TypeInfo().name : "null")
- << ") value has no expression";
+ TINT_IR_ICE(ir_) << "Expr(" << (value ? value->TypeInfo().name : "null")
+ << ") value has no expression";
return {};
}
@@ -926,10 +927,10 @@
}
if constexpr (std::is_same_v<T, ConsumedValue>) {
- TINT_ICE() << "Expr(" << value->TypeInfo().name
- << ") called twice on the same value";
+ TINT_IR_ICE(ir_) << "Expr(" << value->TypeInfo().name
+ << ") called twice on the same value";
} else {
- TINT_ICE()
+ TINT_IR_ICE(ir_)
<< "Expr(" << value->TypeInfo().name << ") has unhandled value";
}
return {};
@@ -999,7 +1000,7 @@
return;
}
- TINT_ICE() << "Bind(" << value->TypeInfo().name << ") called twice for same value";
+ TINT_IR_ICE(ir_) << "Bind(" << value->TypeInfo().name << ") called twice for same value";
}
/// Associates an IR value the 'var', 'let' or parameter of the given name
@@ -1011,7 +1012,8 @@
bool added = bindings_.Add(value, VariableValue{name, ptr_kind});
if (TINT_UNLIKELY(!added)) {
- TINT_ICE() << "Bind(" << value->TypeInfo().name << ") called twice for same value";
+ TINT_IR_ICE(ir_) << "Bind(" << value->TypeInfo().name
+ << ") called twice for same value";
}
}