| //===--- ValueWitness.h - Enumeration of value witnesses --------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the list of witnesses required to attest that a |
| // type is a value type. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_IRGEN_VALUEWITNESS_H |
| #define SWIFT_IRGEN_VALUEWITNESS_H |
| |
| namespace swift { |
| namespace irgen { |
| |
| /// The members required to attest that a type is a value type. |
| /// |
| /// Logically, there are three basic data operations we must support |
| /// on arbitrary types: |
| /// - initializing an object by copying another |
| /// - changing an object to be a copy of another |
| /// - destroying an object |
| /// |
| /// As an optimization to permit efficient transfers of data, the |
| /// "copy" operations each have an analogous "take" operation which |
| /// implicitly destroys the source object. |
| /// |
| /// Therefore there are five basic data operations: |
| /// initWithCopy(T*, T*) |
| /// initWithTake(T*, T*) |
| /// assignWithCopy(T*, T*) |
| /// assignWithTake(T*, T*) |
| /// destroy(T*) |
| /// |
| /// As a further optimization, for every T*, there is a related |
| /// operation which replaces that T* with a B*, combinatorially. This |
| /// makes 18 operations, except that some of these operations are |
| /// fairly unlikely and so do not merit optimized entries, due to |
| /// the common code patterns of the two use cases: |
| /// - Existential code usually doesn't work directly with T*s |
| /// because pointers into existential objects are not generally |
| /// reliable. |
| /// - Generic code works with T*s a fair amount, but it usually |
| /// doesn't have to deal with B*s after initialization |
| /// because initialization returns a reliable pointer. |
| /// This leads us to the following conclusions: |
| // - Operations to copy a B* to a T* are very unlikely |
| /// to be used (-4 operations). |
| /// - Assignments involving two B*s are only likely in |
| /// existential code, where we won't have the right |
| /// typing guarantees to use them (-2 operations). |
| /// Furthermore, take-initializing a buffer from a buffer is just a |
| /// memcpy of the buffer (-1), and take-assigning a buffer from a |
| /// buffer is just a destroy and a memcpy (-1). |
| /// |
| /// This leaves us with 12 data operations, to which we add the |
| /// meta-operation 'sizeAndAlign' for a total of 13. |
| enum class ValueWitness : unsigned { |
| #define WANT_ALL_VALUE_WITNESSES |
| #define VALUE_WITNESS(lowerId, upperId) upperId, |
| #define BEGIN_VALUE_WITNESS_RANGE(rangeId, upperId) First_##rangeId = upperId, |
| #define END_VALUE_WITNESS_RANGE(rangeId, upperId) Last_##rangeId = upperId, |
| #include "swift/ABI/ValueWitness.def" |
| }; |
| |
| enum { |
| NumRequiredValueWitnesses |
| = unsigned(ValueWitness::Last_RequiredValueWitness) + 1, |
| NumRequiredValueWitnessFunctions |
| = unsigned(ValueWitness::Last_RequiredValueWitnessFunction) + 1, |
| |
| MaxNumValueWitnesses |
| = unsigned(ValueWitness::Last_ValueWitness) + 1, |
| MaxNumTypeLayoutWitnesses |
| = unsigned(ValueWitness::Last_TypeLayoutWitness) |
| - unsigned(ValueWitness::First_TypeLayoutWitness) |
| + 1, |
| }; |
| |
| static inline bool isValueWitnessFunction(ValueWitness witness) { |
| #define WANT_ALL_VALUE_WITNESSES 1 |
| #define FUNCTION_VALUE_WITNESS(name, Name, ret, args) \ |
| if (witness == ValueWitness::Name) \ |
| return true; |
| #define DATA_VALUE_WITNESS(name, Name, ty) |
| #include "swift/ABI/ValueWitness.def" |
| |
| return false; |
| } |
| |
| const char *getValueWitnessName(ValueWitness witness); |
| |
| } // end namespace irgen |
| } // end namespace swift |
| |
| #endif |