|
| 1 | +#if SWIFT_PACKAGE |
| 2 | +import cllvm |
| 3 | +#endif |
| 4 | + |
| 5 | +/// An address space is an identifier for a target-specific range of address values. An address space is a |
| 6 | +/// fundamental part of the type of a pointer value and the type of operations that manipulate memory. |
| 7 | +/// |
| 8 | +/// LLVM affords a default address space (numbered zero) and places a number of assumptions on pointer |
| 9 | +/// values within that address space: |
| 10 | +/// - The pointer must have a fixed integral value |
| 11 | +/// - The null pointer has a bit-value of 0 |
| 12 | +/// |
| 13 | +/// These assumptions are not guaranteed to hold in any other address space. In particular, a target may |
| 14 | +/// allow pointers in non-default address spaces to have *non-integral* types. Non-integral pointer types |
| 15 | +/// represent pointers that have an unspecified bitwise representation; that is, the integral representation may |
| 16 | +/// be target dependent or have an unstable value. Further, outside of the default address space, it is not |
| 17 | +/// always the case that the `null` pointer value, especially as returned by |
| 18 | +/// `IRType.constPointerNull()` has a bit value of 0. e.g. A non-default address space may use |
| 19 | +/// an offset-based or segment-based addressing mode in which 0 is a valid, addressable pointer value. |
| 20 | +/// |
| 21 | +/// Target-Level Address Space Overrides |
| 22 | +/// ==================================== |
| 23 | +/// |
| 24 | +/// A target may choose to override the default address space for code, data, and local allocations through the |
| 25 | +/// data layout string. This has multiple uses. For example, the address space of an `alloca` is *only* |
| 26 | +/// configurable via the data layout string, because it is a target-dependent property. There are also |
| 27 | +/// use-cases for overriding language standards e.g. the C standard requires the address-of operator applied |
| 28 | +/// to values on the stack to result in a pointer in the default address space. However, many OpenCL-based |
| 29 | +/// targets consider the stack to be a private region, and place such pointers in a non-default address space. |
| 30 | +/// |
| 31 | +/// Care must be taken when interacting with these non-standard targets. The IR printer currently does not |
| 32 | +/// print anything when the default address space is attached to an instruction or value, and values will still |
| 33 | +/// report being assigned to that space. However, these values are still subject to the backend's interpretation |
| 34 | +/// of the data layout string overrides and as such may not always reside in the default address space when |
| 35 | +/// it comes time to codegen them. |
| 36 | +/// |
| 37 | +/// Restrictions |
| 38 | +/// ============ |
| 39 | +/// |
| 40 | +/// There are currently a number of artificial restrictions on values and operations that have non-default |
| 41 | +/// address spaces: |
| 42 | +/// - A `bitcast` between two pointer values residing in different address spaces, even if those two |
| 43 | +/// values have the same size, is always an illegal operation. Use an `addrspacecast` instead or |
| 44 | +/// always use `IRBuilder.buildPointerCast(of:to:name:)` to get the correct operation. |
| 45 | +/// - The so-called "null pointer" has a bit value that may differ from address space to address space. This |
| 46 | +/// exposes bugs in optimizer passes and lowerings that did not consider this possibility. |
| 47 | +/// - A pointer value may not necessarily "round-trip" when converted between address spaces, even if |
| 48 | +/// annotated `nonnull` and `dereferenceable`. This is especially true of non-integral pointer types. |
| 49 | +/// - Though the zero address space is the default, many backends and some errant passes interpret this to |
| 50 | +/// mean a "lack of address space" and may miscompile code with pointers in mixed address spaces. |
| 51 | +/// - A number of intriniscs that operate on memory currently do not support a non-default address space. |
| 52 | +/// - The address space is ultimately an integer value and in theory an address space identifier may take on |
| 53 | +/// any value. In practice, LLVM guarantees only 24 bits of precision, though higher address space |
| 54 | +/// identifiers may succeed in being properly represented. |
| 55 | +public struct AddressSpace: Equatable { |
| 56 | + let rawValue: Int |
| 57 | + |
| 58 | + /// LLVM's default address space. |
| 59 | + public static let zero = AddressSpace(0) |
| 60 | + |
| 61 | + /// Creates and initializes an address space with the given identifier. |
| 62 | + /// - Parameter identifier: The raw, integral address space identifier. |
| 63 | + public init(_ identifier: Int) { |
| 64 | + self.rawValue = identifier |
| 65 | + } |
| 66 | +} |
0 commit comments