Early out Is checks.

This CL adds a check to the `Is` castable methods to determine if the
target type is `final`. If the type being compared too is `final` we
bail out early in the walk up the hierarchy as it won't be a parent
class.

Change-Id: Ieba4dd686e47207a3db0cf3a8ea46fbc1a8d1c91
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96600
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2022-07-20 15:53:14 +00:00 committed by Dawn LUCI CQ
parent 633cdf41cc
commit 46c32d882d
28 changed files with 72 additions and 62 deletions

View File

@ -117,6 +117,7 @@ def _NonInclusiveFileFilter(file):
"src/dawn/node/tools/src/cmd/run-cts/main.go", # Terminal type name
"src/dawn/samples/ComputeBoids.cpp", # External URL
"src/dawn/tests/end2end/DepthBiasTests.cpp", # External URL
"src/tint/transform/canonicalize_entry_point_io.cc", # External URL
"test/tint/samples/compute_boids.wgsl", # External URL
"third_party/khronos/KHR/khrplatform.h", # Third party file
"tools/roll-all", # Branch name

View File

@ -22,7 +22,7 @@
namespace tint::ast {
/// A float 16 type
class F16 : public Castable<F16, Type> {
class F16 final : public Castable<F16, Type> {
public:
/// Constructor
/// @param pid the identifier of the program that owns this node

View File

@ -20,7 +20,7 @@
namespace tint::ast {
/// An integer literal. The literal may have an 'i', 'u' or no suffix.
class IntLiteralExpression : public Castable<IntLiteralExpression, LiteralExpression> {
class IntLiteralExpression final : public Castable<IntLiteralExpression, LiteralExpression> {
public:
/// Literal suffix
enum class Suffix {

View File

@ -101,6 +101,36 @@ struct TypeInfo {
/// The type hash code bitwise-or'd with all ancestor's hashcodes.
const HashCode full_hashcode;
/// @returns true if `type` derives from the class `TO`
/// @param object the object type to test from, which must be, or derive from
/// type `FROM`.
/// @see CastFlags
template <typename TO, typename FROM, int FLAGS = 0>
static inline bool Is(const tint::TypeInfo* object) {
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
constexpr const bool nocast = std::is_same<FROM, TO>::value;
constexpr const bool assert_is_castable = (FLAGS & kDontErrorOnImpossibleCast) == 0;
static_assert(upcast || downcast || nocast || !assert_is_castable, "impossible cast");
return upcast || nocast || object->Is<TO>();
}
/// @returns true if this type derives from the class `T`
template <typename T>
inline bool Is() const {
auto* type = &Of<std::remove_cv_t<T>>();
if constexpr (std::is_final_v<T>) {
// T is final, so nothing can derive from T.
// We do not need to check ancestors, only whether this type is equal to the type T.
return type == this;
} else {
return Is(type);
}
}
/// @param type the test type info
/// @returns true if the class with this TypeInfo is of, or derives from the
/// class with the given TypeInfo.
@ -112,8 +142,8 @@ struct TypeInfo {
return false;
}
// Walk the base types, starting with this TypeInfo, to see if any of the
// pointers match `type`.
// Walk the base types, starting with this TypeInfo, to see if any of the pointers match
// `type`.
for (auto* ti = this; ti != nullptr; ti = ti->base) {
if (ti == type) {
return true;
@ -122,26 +152,6 @@ struct TypeInfo {
return false;
}
/// @returns true if `type` derives from the class `TO`
/// @param type the object type to test from, which must be, or derive from
/// type `FROM`.
/// @see CastFlags
template <typename TO, typename FROM, int FLAGS = 0>
static inline bool Is(const tint::TypeInfo* type) {
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
constexpr const bool nocast = std::is_same<FROM, TO>::value;
constexpr const bool assert_is_castable = (FLAGS & kDontErrorOnImpossibleCast) == 0;
static_assert(upcast || downcast || nocast || !assert_is_castable, "impossible cast");
if (upcast || nocast) {
return true;
}
return type->Is(&Of<std::remove_cv_t<TO>>());
}
/// @returns the static TypeInfo for the type T
template <typename T>
static const TypeInfo& Of() {
@ -211,14 +221,12 @@ struct TypeInfo {
if constexpr (kCount == 0) {
return false;
} else if constexpr (kCount == 1) {
return Is(&Of<std::tuple_element_t<0, TUPLE>>());
return Is<std::tuple_element_t<0, TUPLE>>();
} else if constexpr (kCount == 2) {
return Is(&Of<std::tuple_element_t<0, TUPLE>>()) ||
Is(&Of<std::tuple_element_t<1, TUPLE>>());
return Is<std::tuple_element_t<0, TUPLE>>() || Is<std::tuple_element_t<1, TUPLE>>();
} else if constexpr (kCount == 3) {
return Is(&Of<std::tuple_element_t<0, TUPLE>>()) ||
Is(&Of<std::tuple_element_t<1, TUPLE>>()) ||
Is(&Of<std::tuple_element_t<2, TUPLE>>());
return Is<std::tuple_element_t<0, TUPLE>>() || Is<std::tuple_element_t<1, TUPLE>>() ||
Is<std::tuple_element_t<2, TUPLE>>();
} else {
// Optimization: Compare the object's hashcode to the bitwise-or of all
// the tested type's hashcodes. If there's no intersection of bits in
@ -587,7 +595,7 @@ inline bool NonDefaultCases(T* object,
// Attempt to dynamically cast the object to the handler type. If that
// succeeds, call the case handler with the cast object.
using CaseType = SwitchCaseType<CaseFunc>;
if (type->Is(&TypeInfo::Of<CaseType>())) {
if (type->Is<CaseType>()) {
auto* ptr = static_cast<CaseType*>(object);
if constexpr (kHasReturnType) {
new (result) RETURN_TYPE(static_cast<RETURN_TYPE>(std::get<0>(cases)(ptr)));

View File

@ -22,7 +22,7 @@
namespace tint::sem {
/// A float 16 type
class F16 : public Castable<F16, Type> {
class F16 final : public Castable<F16, Type> {
public:
/// Constructor
F16();

View File

@ -170,7 +170,7 @@ class Struct final : public Castable<Struct, Type> {
};
/// StructMember holds the semantic information for structure members.
class StructMember : public Castable<StructMember, Node> {
class StructMember final : public Castable<StructMember, Node> {
public:
/// Constructor
/// @param declaration the AST declaration node

View File

@ -73,7 +73,7 @@ struct OffsetExpr : Offset {
/// OffsetLiteral is an implementation of Offset that constructs a u32 literal
/// value.
struct OffsetLiteral : Castable<OffsetLiteral, Offset> {
struct OffsetLiteral final : Castable<OffsetLiteral, Offset> {
uint32_t const literal = 0;
explicit OffsetLiteral(uint32_t lit) : literal(lit) {}

View File

@ -38,7 +38,7 @@ namespace tint::transform {
///
/// This transform also handles increment and decrement statements in the same
/// manner, by replacing `i++` with `i = i + 1`.
class ExpandCompoundAssignment : public Castable<ExpandCompoundAssignment, Transform> {
class ExpandCompoundAssignment final : public Castable<ExpandCompoundAssignment, Transform> {
public:
/// Constructor
ExpandCompoundAssignment();

View File

@ -27,7 +27,8 @@ namespace tint::transform {
///
/// @note Depends on the following transforms to have been run first:
/// * SimplifyPointers
class LocalizeStructArrayAssignment : public Castable<LocalizeStructArrayAssignment, Transform> {
class LocalizeStructArrayAssignment final
: public Castable<LocalizeStructArrayAssignment, Transform> {
public:
/// Constructor
LocalizeStructArrayAssignment();

View File

@ -21,7 +21,7 @@ namespace tint::transform {
/// LoopToForLoop is a Transform that attempts to convert WGSL `loop {}`
/// statements into a for-loop statement.
class LoopToForLoop : public Castable<LoopToForLoop, Transform> {
class LoopToForLoop final : public Castable<LoopToForLoop, Transform> {
public:
/// Constructor
LoopToForLoop();

View File

@ -27,7 +27,7 @@ namespace tint::transform {
/// The inner transforms will execute in the appended order.
/// If any inner transform fails the manager will return immediately and
/// the error can be retrieved with the Output's diagnostics.
class Manager : public Castable<Manager, Transform> {
class Manager final : public Castable<Manager, Transform> {
public:
/// Constructor
Manager();

View File

@ -61,7 +61,7 @@ namespace tint::transform {
/// foo(&p, sptr);
/// }
/// ```
class ModuleScopeVarToEntryPointParam
class ModuleScopeVarToEntryPointParam final
: public Castable<ModuleScopeVarToEntryPointParam, Transform> {
public:
/// Constructor

View File

@ -50,7 +50,7 @@ struct BindingPoints {
/// decoding, gamut conversion, and gamma encoding steps. Specifically
// for BT.709 to SRGB conversion, it takes the fast path only doing the yuv->rgb
// step and skipping all other steps.
class MultiplanarExternalTexture : public Castable<MultiplanarExternalTexture, Transform> {
class MultiplanarExternalTexture final : public Castable<MultiplanarExternalTexture, Transform> {
public:
/// BindingsMap is a map where the key is the binding location of a
/// texture_external and the value is a struct containing the desired
@ -60,7 +60,7 @@ class MultiplanarExternalTexture : public Castable<MultiplanarExternalTexture, T
/// NewBindingPoints is consumed by the MultiplanarExternalTexture transform.
/// Data holds information about location of each texture_external binding and
/// which binding slots it should expand into.
struct NewBindingPoints : public Castable<Data, transform::Data> {
struct NewBindingPoints final : public Castable<Data, transform::Data> {
/// Constructor
/// @param bm a map to the new binding slots to use.
explicit NewBindingPoints(BindingsMap bm);

View File

@ -44,7 +44,7 @@ namespace tint::transform {
///
/// @note Depends on the following transforms to have been run first:
/// * CanonicalizeEntryPointIO
class NumWorkgroupsFromUniform : public Castable<NumWorkgroupsFromUniform, Transform> {
class NumWorkgroupsFromUniform final : public Castable<NumWorkgroupsFromUniform, Transform> {
public:
/// Constructor
NumWorkgroupsFromUniform();
@ -52,7 +52,7 @@ class NumWorkgroupsFromUniform : public Castable<NumWorkgroupsFromUniform, Trans
~NumWorkgroupsFromUniform() override;
/// Configuration options for the NumWorkgroupsFromUniform transform.
struct Config : public Castable<Data, transform::Data> {
struct Config final : public Castable<Data, transform::Data> {
/// Constructor
/// @param ubo_bp the binding point to use for the generated uniform buffer. If ubo_bp
/// contains no value, a free binding point will be used to ensure the generated program is

View File

@ -25,7 +25,7 @@ namespace tint::transform {
/// array or structure. For example, the following is not immediately expressable for HLSL:
/// `array<i32, 2>(1, 2)[0]`
/// @see crbug.com/tint/406
class PromoteInitializersToLet : public Castable<PromoteInitializersToLet, Transform> {
class PromoteInitializersToLet final : public Castable<PromoteInitializersToLet, Transform> {
public:
/// Constructor
PromoteInitializersToLet();

View File

@ -23,7 +23,7 @@ namespace tint::transform {
/// declarations before the statement of usage with the goal of ensuring
/// left-to-right order of evaluation, while respecting short-circuit
/// evaluation.
class PromoteSideEffectsToDecl : public Castable<PromoteSideEffectsToDecl, Transform> {
class PromoteSideEffectsToDecl final : public Castable<PromoteSideEffectsToDecl, Transform> {
public:
/// Constructor
PromoteSideEffectsToDecl();

View File

@ -23,7 +23,7 @@ namespace tint::transform {
/// bool variable, and checking if the variable is set after the switch to
/// continue. It is necessary to work around FXC "error X3708: continue cannot
/// be used in a switch". See crbug.com/tint/1080.
class RemoveContinueInSwitch : public Castable<RemoveContinueInSwitch, Transform> {
class RemoveContinueInSwitch final : public Castable<RemoveContinueInSwitch, Transform> {
public:
/// Constructor
RemoveContinueInSwitch();

View File

@ -25,7 +25,7 @@ namespace tint::transform {
/// RemovePhonies is a Transform that removes all phony-assignment statements,
/// while preserving function call expressions in the RHS of the assignment that
/// may have side-effects.
class RemovePhonies : public Castable<RemovePhonies, Transform> {
class RemovePhonies final : public Castable<RemovePhonies, Transform> {
public:
/// Constructor
RemovePhonies();

View File

@ -24,7 +24,7 @@ namespace tint::transform {
/// RemoveUnreachableStatements is a Transform that removes all statements
/// marked as unreachable.
class RemoveUnreachableStatements : public Castable<RemoveUnreachableStatements, Transform> {
class RemoveUnreachableStatements final : public Castable<RemoveUnreachableStatements, Transform> {
public:
/// Constructor
RemoveUnreachableStatements();

View File

@ -23,11 +23,11 @@
namespace tint::transform {
/// Renamer is a Transform that renames all the symbols in a program.
class Renamer : public Castable<Renamer, Transform> {
class Renamer final : public Castable<Renamer, Transform> {
public:
/// Data is outputted by the Renamer transform.
/// Data holds information about shader usage and constant buffer offsets.
struct Data : public Castable<Data, transform::Data> {
struct Data final : public Castable<Data, transform::Data> {
/// Remappings is a map of old symbol name to new symbol name
using Remappings = std::unordered_map<std::string, std::string>;
@ -59,7 +59,7 @@ class Renamer : public Castable<Renamer, Transform> {
/// Optional configuration options for the transform.
/// If omitted, then the renamer will use Target::kAll.
struct Config : public Castable<Config, transform::Data> {
struct Config final : public Castable<Config, transform::Data> {
/// Constructor
/// @param tgt the targets to rename
/// @param keep_unicode if false, symbols with non-ascii code-points are

View File

@ -31,7 +31,7 @@ namespace tint::transform {
/// the bounds of the array. Any access before the start of the array will clamp
/// to zero and any access past the end of the array will clamp to
/// (array length - 1).
class Robustness : public Castable<Robustness, Transform> {
class Robustness final : public Castable<Robustness, Transform> {
public:
/// Storage class to be skipped in the transform
enum class StorageClass {
@ -40,7 +40,7 @@ class Robustness : public Castable<Robustness, Transform> {
};
/// Configuration options for the transform
struct Config : public Castable<Config, Data> {
struct Config final : public Castable<Config, Data> {
/// Constructor
Config();

View File

@ -31,7 +31,7 @@ namespace tint::transform {
///
/// @note Depends on the following transforms to have been run first:
/// * Unshadow
class SimplifyPointers : public Castable<SimplifyPointers, Transform> {
class SimplifyPointers final : public Castable<SimplifyPointers, Transform> {
public:
/// Constructor
SimplifyPointers();

View File

@ -25,10 +25,10 @@ namespace tint::transform {
///
/// All module-scope variables, types, and functions that are not used by the
/// target entry point will also be removed.
class SingleEntryPoint : public Castable<SingleEntryPoint, Transform> {
class SingleEntryPoint final : public Castable<SingleEntryPoint, Transform> {
public:
/// Configuration options for the transform
struct Config : public Castable<Config, Data> {
struct Config final : public Castable<Config, Data> {
/// Constructor
/// @param entry_point the name of the entry point to keep
explicit Config(std::string entry_point = "");

View File

@ -21,7 +21,7 @@ namespace tint::transform {
/// Unshadow is a Transform that renames any variables that shadow another
/// variable.
class Unshadow : public Castable<Unshadow, Transform> {
class Unshadow final : public Castable<Unshadow, Transform> {
public:
/// Constructor
Unshadow();

View File

@ -36,7 +36,7 @@ namespace tint::transform {
///
/// @note Depends on the following transforms to have been run first:
/// * PromoteSideEffectsToDecl
class UnwindDiscardFunctions : public Castable<UnwindDiscardFunctions, Transform> {
class UnwindDiscardFunctions final : public Castable<UnwindDiscardFunctions, Transform> {
public:
/// Constructor
UnwindDiscardFunctions();

View File

@ -20,7 +20,7 @@
namespace tint::transform {
/// A transform that converts scalar matrix constructors to the vector form.
class VectorizeScalarMatrixConstructors
class VectorizeScalarMatrixConstructors final
: public Castable<VectorizeScalarMatrixConstructors, Transform> {
public:
/// Constructor

View File

@ -128,10 +128,10 @@ using VertexStateDescriptor = std::vector<VertexBufferLayoutDescriptor>;
/// code, but these are types that the data may arrive as. We need to convert
/// these smaller types into the base types such as `f32` and `u32` for the
/// shader to use.
class VertexPulling : public Castable<VertexPulling, Transform> {
class VertexPulling final : public Castable<VertexPulling, Transform> {
public:
/// Configuration options for the transform
struct Config : public Castable<Config, Data> {
struct Config final : public Castable<Config, Data> {
/// Constructor
Config();

View File

@ -22,7 +22,7 @@ namespace tint::transform {
/// ZeroInitWorkgroupMemory is a transform that injects code at the top of entry
/// points to zero-initialize workgroup memory used by that entry point (and all
/// transitive functions called by that entry point)
class ZeroInitWorkgroupMemory : public Castable<ZeroInitWorkgroupMemory, Transform> {
class ZeroInitWorkgroupMemory final : public Castable<ZeroInitWorkgroupMemory, Transform> {
public:
/// Constructor
ZeroInitWorkgroupMemory();