mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-09-01 00:10:30 +00:00
The dependency graph no longer errors if a symbol cannot be resolved, instead the ResolvedIdentifier now has an unresolved variant. This is required as the second resolve phase only has the full context of the identifier usage, to provide the hints. Also: Split Slice out of the utils/vector.h, so it can be used as a lightweight view over static data. Fixed: tint:1842 Change-Id: I31fa7697790be24c35b7e4fab5ca903c8a7afbba Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121020 Commit-Queue: Ben Clayton <bclayton@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
206 lines
7.1 KiB
C++
206 lines
7.1 KiB
C++
// Copyright 2023 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef SRC_TINT_UTILS_SLICE_H_
|
|
#define SRC_TINT_UTILS_SLICE_H_
|
|
|
|
#include <cstdint>
|
|
#include <iterator>
|
|
|
|
#include "src/tint/castable.h"
|
|
#include "src/tint/traits.h"
|
|
|
|
namespace tint::utils {
|
|
|
|
/// A type used to indicate an empty array.
|
|
struct EmptyType {};
|
|
|
|
/// An instance of the EmptyType.
|
|
static constexpr EmptyType Empty;
|
|
|
|
/// Mode enumerator for ReinterpretSlice
|
|
enum class ReinterpretMode {
|
|
/// Only upcasts of pointers are permitted
|
|
kSafe,
|
|
/// Potentially unsafe downcasts of pointers are also permitted
|
|
kUnsafe,
|
|
};
|
|
|
|
namespace detail {
|
|
|
|
template <typename TO, typename FROM>
|
|
static constexpr bool ConstRemoved = std::is_const_v<FROM> && !std::is_const_v<TO>;
|
|
|
|
/// Private implementation of tint::utils::CanReinterpretSlice.
|
|
/// Specialized for the case of TO equal to FROM, which is the common case, and avoids inspection of
|
|
/// the base classes, which can be troublesome if the slice is of an incomplete type.
|
|
template <ReinterpretMode MODE, typename TO, typename FROM>
|
|
struct CanReinterpretSlice {
|
|
private:
|
|
using TO_EL = std::remove_pointer_t<std::decay_t<TO>>;
|
|
using FROM_EL = std::remove_pointer_t<std::decay_t<FROM>>;
|
|
|
|
public:
|
|
/// @see utils::CanReinterpretSlice
|
|
static constexpr bool value =
|
|
// const can only be applied, not removed
|
|
!ConstRemoved<TO, FROM> &&
|
|
|
|
// Both TO and FROM are the same type (ignoring const)
|
|
(std::is_same_v<std::remove_const_t<TO>, std::remove_const_t<FROM>> ||
|
|
|
|
// Both TO and FROM are pointers...
|
|
((std::is_pointer_v<TO> && std::is_pointer_v<FROM>)&&
|
|
|
|
// const can only be applied to element type, not removed
|
|
!ConstRemoved<TO_EL, FROM_EL> &&
|
|
|
|
// Either:
|
|
// * Both the pointer elements are of the same type (ignoring const)
|
|
// * Both the pointer elements are both Castable, and MODE is kUnsafe, or FROM is of,
|
|
// or
|
|
// derives from TO
|
|
(std::is_same_v<std::remove_const_t<FROM_EL>, std::remove_const_t<TO_EL>> ||
|
|
(IsCastable<FROM_EL, TO_EL> &&
|
|
(MODE == ReinterpretMode::kUnsafe || traits::IsTypeOrDerived<FROM_EL, TO_EL>)))));
|
|
};
|
|
|
|
/// Specialization of 'CanReinterpretSlice' for when TO and FROM are equal types.
|
|
template <typename T, ReinterpretMode MODE>
|
|
struct CanReinterpretSlice<MODE, T, T> {
|
|
/// Always `true` as TO and FROM are the same type.
|
|
static constexpr bool value = true;
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
/// Evaluates whether a `Slice<FROM>` and be reinterpreted as a `Slice<TO>`.
|
|
/// Slices can be reinterpreted if:
|
|
/// * TO has the same or more 'constness' than FROM.
|
|
/// * And either:
|
|
/// * `FROM` and `TO` are pointers to the same type
|
|
/// * `FROM` and `TO` are pointers to CastableBase (or derived), and the pointee type of `TO` is of
|
|
/// the same type as, or is an ancestor of the pointee type of `FROM`.
|
|
template <ReinterpretMode MODE, typename TO, typename FROM>
|
|
static constexpr bool CanReinterpretSlice = detail::CanReinterpretSlice<MODE, TO, FROM>::value;
|
|
|
|
/// A slice represents a contigious array of elements of type T.
|
|
template <typename T>
|
|
struct Slice {
|
|
/// Type of `T`.
|
|
using value_type = T;
|
|
|
|
/// The pointer to the first element in the slice
|
|
T* data = nullptr;
|
|
|
|
/// The total number of elements in the slice
|
|
size_t len = 0;
|
|
|
|
/// The total capacity of the backing store for the slice
|
|
size_t cap = 0;
|
|
|
|
/// Constructor
|
|
Slice() = default;
|
|
|
|
/// Constructor
|
|
Slice(EmptyType) {} // NOLINT
|
|
|
|
/// Constructor
|
|
/// @param d pointer to the first element in the slice
|
|
/// @param l total number of elements in the slice
|
|
/// @param c total capacity of the backing store for the slice
|
|
Slice(T* d, size_t l, size_t c) : data(d), len(l), cap(c) {}
|
|
|
|
/// Constructor
|
|
/// @param elements c-array of elements
|
|
template <size_t N>
|
|
Slice(T (&elements)[N]) // NOLINT
|
|
: data(elements), len(N), cap(N) {}
|
|
|
|
/// Reinterprets this slice as `const Slice<TO>&`
|
|
/// @returns the reinterpreted slice
|
|
/// @see CanReinterpretSlice
|
|
template <typename TO, ReinterpretMode MODE = ReinterpretMode::kSafe>
|
|
const Slice<TO>& Reinterpret() const {
|
|
static_assert(CanReinterpretSlice<MODE, TO, T>);
|
|
return *Bitcast<const Slice<TO>*>(this);
|
|
}
|
|
|
|
/// Reinterprets this slice as `Slice<TO>&`
|
|
/// @returns the reinterpreted slice
|
|
/// @see CanReinterpretSlice
|
|
template <typename TO, ReinterpretMode MODE = ReinterpretMode::kSafe>
|
|
Slice<TO>& Reinterpret() {
|
|
static_assert(CanReinterpretSlice<MODE, TO, T>);
|
|
return *Bitcast<Slice<TO>*>(this);
|
|
}
|
|
|
|
/// @return true if the slice length is zero
|
|
bool IsEmpty() const { return len == 0; }
|
|
|
|
/// Index operator
|
|
/// @param i the element index. Must be less than `len`.
|
|
/// @returns a reference to the i'th element.
|
|
T& operator[](size_t i) { return data[i]; }
|
|
|
|
/// Index operator
|
|
/// @param i the element index. Must be less than `len`.
|
|
/// @returns a reference to the i'th element.
|
|
const T& operator[](size_t i) const { return data[i]; }
|
|
|
|
/// @returns a reference to the first element in the vector
|
|
T& Front() { return data[0]; }
|
|
|
|
/// @returns a reference to the first element in the vector
|
|
const T& Front() const { return data[0]; }
|
|
|
|
/// @returns a reference to the last element in the vector
|
|
T& Back() { return data[len - 1]; }
|
|
|
|
/// @returns a reference to the last element in the vector
|
|
const T& Back() const { return data[len - 1]; }
|
|
|
|
/// @returns a pointer to the first element in the vector
|
|
T* begin() { return data; }
|
|
|
|
/// @returns a pointer to the first element in the vector
|
|
const T* begin() const { return data; }
|
|
|
|
/// @returns a pointer to one past the last element in the vector
|
|
T* end() { return data + len; }
|
|
|
|
/// @returns a pointer to one past the last element in the vector
|
|
const T* end() const { return data + len; }
|
|
|
|
/// @returns a reverse iterator starting with the last element in the vector
|
|
auto rbegin() { return std::reverse_iterator<T*>(end()); }
|
|
|
|
/// @returns a reverse iterator starting with the last element in the vector
|
|
auto rbegin() const { return std::reverse_iterator<const T*>(end()); }
|
|
|
|
/// @returns the end for a reverse iterator
|
|
auto rend() { return std::reverse_iterator<T*>(begin()); }
|
|
|
|
/// @returns the end for a reverse iterator
|
|
auto rend() const { return std::reverse_iterator<const T*>(begin()); }
|
|
};
|
|
|
|
/// Deduction guide for Slice from c-array
|
|
template <typename T, size_t N>
|
|
Slice(T (&elements)[N]) -> Slice<T>;
|
|
|
|
} // namespace tint::utils
|
|
|
|
#endif // SRC_TINT_UTILS_SLICE_H_
|