mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
105 lines
3.8 KiB
C++
105 lines
3.8 KiB
C++
//===--- 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
|