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:
parent
633cdf41cc
commit
46c32d882d
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace tint::transform {
|
|||
/// foo(&p, sptr);
|
||||
/// }
|
||||
/// ```
|
||||
class ModuleScopeVarToEntryPointParam
|
||||
class ModuleScopeVarToEntryPointParam final
|
||||
: public Castable<ModuleScopeVarToEntryPointParam, Transform> {
|
||||
public:
|
||||
/// Constructor
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 = "");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue