Skip to content

Add arm64e and pointer authentication support for Swift #30112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ endmacro()

macro(configure_sdks_darwin)
set(macosx_arch "x86_64")
set(iphoneos_arch "arm64" "armv7")
set(iphoneos_arch "arm64" "arm64e" "armv7")
set(appletvos_arch "arm64")
set(watchos_arch "armv7k")

Expand Down
4 changes: 2 additions & 2 deletions cmake/modules/DarwinSDKs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ option(SWIFT_ENABLE_IOS32
TRUE)

if(SWIFT_ENABLE_IOS32)
set(SUPPORTED_IOS_ARCHS "armv7;armv7s;arm64")
set(SUPPORTED_IOS_ARCHS "armv7;armv7s;arm64;arm64e")
set(SUPPORTED_IOS_SIMULATOR_ARCHS "i386;x86_64")
else()
set(SUPPORTED_IOS_ARCHS "arm64")
set(SUPPORTED_IOS_ARCHS "arm64;arm64e")
set(SUPPORTED_IOS_SIMULATOR_ARCHS "x86_64")
endif()

Expand Down
1 change: 1 addition & 0 deletions cmake/modules/SwiftSetIfArchBitness.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function(set_if_arch_bitness var_name)
set("${var_name}" "${SIA_CASE_32_BIT}" PARENT_SCOPE)
elseif("${SIA_ARCH}" STREQUAL "x86_64" OR
"${SIA_ARCH}" STREQUAL "arm64" OR
"${SIA_ARCH}" STREQUAL "arm64e" OR
"${SIA_ARCH}" STREQUAL "aarch64" OR
"${SIA_ARCH}" STREQUAL "powerpc64" OR
"${SIA_ARCH}" STREQUAL "powerpc64le" OR
Expand Down
126 changes: 93 additions & 33 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ struct RuntimeTarget;
template <>
struct RuntimeTarget<4> {
using StoredPointer = uint32_t;
// To avoid implicit conversions from StoredSignedPointer to StoredPointer.
using StoredSignedPointer = struct {
uint32_t SignedValue;
};
using StoredSize = uint32_t;
using StoredPointerDifference = int32_t;
static constexpr size_t PointerSize = 4;
Expand All @@ -61,6 +65,10 @@ struct RuntimeTarget<4> {
template <>
struct RuntimeTarget<8> {
using StoredPointer = uint64_t;
// To avoid implicit conversions from StoredSignedPointer to StoredPointer.
using StoredSignedPointer = struct {
uint64_t SignedValue;
};
using StoredSize = uint64_t;
using StoredPointerDifference = int64_t;
static constexpr size_t PointerSize = 8;
Expand All @@ -77,6 +85,7 @@ namespace reflection {
struct InProcess {
static constexpr size_t PointerSize = sizeof(uintptr_t);
using StoredPointer = uintptr_t;
using StoredSignedPointer = uintptr_t;
using StoredSize = size_t;
using StoredPointerDifference = ptrdiff_t;

Expand All @@ -85,6 +94,9 @@ struct InProcess {

template <typename T>
using Pointer = T*;

template <typename T>
using SignedPointer = T;

template <typename T, bool Nullable = false>
using FarRelativeDirectPointer = FarRelativeDirectPointer<T, Nullable>;
Expand All @@ -111,13 +123,17 @@ struct ExternalPointer {
template <typename Runtime>
struct External {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSignedPointer = typename Runtime::StoredSignedPointer;
using StoredSize = typename Runtime::StoredSize;
using StoredPointerDifference = typename Runtime::StoredPointerDifference;
static constexpr size_t PointerSize = Runtime::PointerSize;
const StoredPointer PointerValue;

template <typename T>
using Pointer = StoredPointer;

template <typename T>
using SignedPointer = StoredSignedPointer;

template <typename T, bool Nullable = false>
using FarRelativeDirectPointer = StoredPointer;
Expand All @@ -141,9 +157,13 @@ using ConstTargetMetadataPointer
template <typename Runtime, typename T>
using TargetPointer = typename Runtime::template Pointer<T>;

template <typename Runtime, typename T>
using TargetSignedPointer = typename Runtime::template SignedPointer<T>;

template <typename Runtime, typename T>
using ConstTargetPointer = typename Runtime::template Pointer<const T>;


template <typename Runtime, template <typename> class Pointee,
bool Nullable = true>
using ConstTargetFarRelativeDirectPointer
Expand Down Expand Up @@ -281,7 +301,10 @@ class TargetValueWitnessTypes {
#define WANT_ALL_VALUE_WITNESSES
#define DATA_VALUE_WITNESS(lowerId, upperId, type)
#define FUNCTION_VALUE_WITNESS(lowerId, upperId, returnType, paramTypes) \
typedef TargetPointer<Runtime, returnType paramTypes> lowerId;
typedef returnType (*lowerId ## Unsigned) paramTypes; \
typedef TargetSignedPointer<Runtime, lowerId ## Unsigned \
__ptrauth_swift_value_witness_function_pointer( \
SpecialPointerAuthDiscriminators::upperId)> lowerId;
#define MUTABLE_VALUE_TYPE TargetPointer<Runtime, OpaqueValue>
#define IMMUTABLE_VALUE_TYPE ConstTargetPointer<Runtime, OpaqueValue>
#define MUTABLE_BUFFER_TYPE TargetPointer<Runtime, ValueBuffer>
Expand Down Expand Up @@ -314,6 +337,9 @@ template <typename Runtime> struct TargetValueWitnessTable {
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID;
#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RET, PARAMS) \
typename TargetValueWitnessTypes<Runtime>::LOWER_ID LOWER_ID;

#include "swift/ABI/ValueWitness.def"

using StoredSize = typename Runtime::StoredSize;
Expand Down Expand Up @@ -595,7 +621,7 @@ struct TargetMetadata {
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \
template<typename...A> \
_ResultOf<ValueWitnessTypes::WITNESS>::type \
_ResultOf<ValueWitnessTypes::WITNESS ## Unsigned>::type \
vw_##WITNESS(A &&...args) const { \
return getValueWitnesses()->WITNESS(std::forward<A>(args)..., this); \
}
Expand Down Expand Up @@ -744,7 +770,7 @@ template <typename Runtime>
struct TargetHeapMetadataHeaderPrefix {
/// Destroy the object, returning the allocated size of the object
/// or 0 if the object shouldn't be deallocated.
TargetPointer<Runtime, HeapObjectDestroyer> destroy;
TargetSignedPointer<Runtime, HeapObjectDestroyer *__ptrauth_swift_heap_object_destructor> destroy;
};
using HeapMetadataHeaderPrefix =
TargetHeapMetadataHeaderPrefix<InProcess>;
Expand Down Expand Up @@ -838,18 +864,26 @@ struct TargetVTableDescriptorHeader {

template<typename Runtime> struct TargetContextDescriptor;

template<typename Runtime>
template<typename Runtime,
template<typename _Runtime> class Context = TargetContextDescriptor>
using TargetSignedContextPointer = TargetSignedPointer<Runtime,
Context<Runtime> * __ptrauth_swift_type_descriptor>;

template<typename Runtime,
template<typename _Runtime> class Context = TargetContextDescriptor>
using TargetRelativeContextPointer =
RelativeIndirectablePointer<const TargetContextDescriptor<Runtime>,
/*nullable*/ true>;
RelativeIndirectablePointer<const Context<Runtime>,
/*nullable*/ true, int32_t,
TargetSignedContextPointer<Runtime, Context>>;

using RelativeContextPointer = TargetRelativeContextPointer<InProcess>;

template<typename Runtime, typename IntTy,
template<typename _Runtime> class Context = TargetContextDescriptor>
using RelativeContextPointerIntPair =
RelativeIndirectablePointerIntPair<const Context<Runtime>, IntTy,
/*nullable*/ true, int32_t>;
/*nullable*/ true, int32_t,
TargetSignedContextPointer<Runtime, Context>>;

template<typename Runtime> struct TargetMethodDescriptor;

Expand Down Expand Up @@ -1085,13 +1119,13 @@ struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
/// if this is an artificial subclass. We currently provide no
/// supported mechanism for making a non-artificial subclass
/// dynamically.
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor> Description;
TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

public:
/// A function for destroying instance variables, used to clean up after an
/// early return from a constructor. If null, no clean up will be performed
/// and all ivars must be trivial.
TargetPointer<Runtime, ClassIVarDestroyer> IVarDestroyer;
TargetSignedPointer<Runtime, ClassIVarDestroyer * __ptrauth_swift_heap_object_destructor> IVarDestroyer;

// After this come the class members, laid out as follows:
// - class members for the superclass (recursively)
Expand All @@ -1108,6 +1142,12 @@ struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
return Description;
}

typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
assert(isTypeMetadata());
return Description;
}

void setDescription(const TargetClassDescriptor<Runtime> *description) {
Description = description;
}
Expand Down Expand Up @@ -1314,7 +1354,7 @@ struct TargetForeignClassMetadata : public TargetForeignTypeMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;

/// An out-of-line description of the type.
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor> Description;
TargetSignedPointer<Runtime, const TargetClassDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

/// The superclass of the foreign class, if any.
ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
Expand All @@ -1330,6 +1370,11 @@ struct TargetForeignClassMetadata : public TargetForeignTypeMetadata<Runtime> {
return Description;
}

typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
return Description;
}

static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::ForeignClass;
}
Expand All @@ -1345,8 +1390,7 @@ struct TargetValueMetadata : public TargetMetadata<Runtime> {
: TargetMetadata<Runtime>(Kind), Description(description) {}

/// An out-of-line description of the type.
ConstTargetMetadataPointer<Runtime, TargetValueTypeDescriptor>
Description;
TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;

static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
Expand All @@ -1358,6 +1402,11 @@ struct TargetValueMetadata : public TargetMetadata<Runtime> {
getDescription() const {
return Description;
}

typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
return Description;
}
};
using ValueMetadata = TargetValueMetadata<InProcess>;

Expand Down Expand Up @@ -2189,7 +2238,7 @@ struct TargetTypeMetadataRecord {
DirectNominalTypeDescriptor;

/// An indirect reference to a nominal type descriptor.
RelativeDirectPointerIntPair<TargetContextDescriptor<Runtime> * const,
RelativeDirectPointerIntPair<TargetSignedPointer<Runtime, TargetContextDescriptor<Runtime> * __ptrauth_swift_type_descriptor>,
TypeReferenceKind>
IndirectNominalTypeDescriptor;

Expand Down Expand Up @@ -2242,24 +2291,25 @@ template<typename Runtime> class TargetGenericRequirementDescriptor;
/// pointer equivalent to \c TargetProtocolDescriptorRef.
template <typename Runtime>
class RelativeTargetProtocolDescriptorPointer {
union AnyProtocol {
TargetProtocolDescriptor<Runtime> descriptor;
union {
/// Relative pointer to a Swift protocol descriptor.
/// The \c bool value will be false to indicate that the protocol
/// is a Swift protocol, or true to indicate that this references
/// an Objective-C protocol.
RelativeContextPointerIntPair<Runtime, bool, TargetProtocolDescriptor>
swiftPointer;
#if SWIFT_OBJC_INTEROP
/// Relative pointer to an ObjC protocol descriptor.
/// The \c bool value will be false to indicate that the protocol
/// is a Swift protocol, or true to indicate that this references
/// an Objective-C protocol.
RelativeIndirectablePointerIntPair<Protocol, bool> objcPointer;
#endif
};

/// The relative pointer itself.
///
/// The \c AnyProtocol value type ensures that we can reference any
/// protocol descriptor; it will be reinterpret_cast to the appropriate
/// protocol descriptor type.
///
/// The \c bool integer value will be false to indicate that the protocol
/// is a Swift protocol, or true to indicate that this references
/// an Objective-C protocol.
RelativeIndirectablePointerIntPair<AnyProtocol, bool> pointer;

#if SWIFT_OBJC_INTEROP
bool isObjC() const {
return pointer.getInt();
return objcPointer.getInt();
}
#endif

Expand All @@ -2269,13 +2319,13 @@ class RelativeTargetProtocolDescriptorPointer {
#if SWIFT_OBJC_INTEROP
if (isObjC()) {
return TargetProtocolDescriptorRef<Runtime>::forObjC(
protocol_const_cast(pointer.getPointer()));
const_cast<Protocol*>(objcPointer.getPointer()));
}
#endif

return TargetProtocolDescriptorRef<Runtime>::forSwift(
reinterpret_cast<ConstTargetMetadataPointer<
Runtime, TargetProtocolDescriptor>>(pointer.getPointer()));
Runtime, TargetProtocolDescriptor>>(swiftPointer.getPointer()));
}

operator TargetProtocolDescriptorRef<Runtime>() const {
Expand All @@ -2293,7 +2343,7 @@ struct TargetTypeReference {

/// An indirect reference to a TypeContextDescriptor or ProtocolDescriptor.
RelativeDirectPointer<
ConstTargetMetadataPointer<Runtime, TargetContextDescriptor>>
TargetSignedPointer<Runtime, TargetContextDescriptor<Runtime> * __ptrauth_swift_type_descriptor>>
IndirectTypeDescriptor;

/// An indirect reference to an Objective-C class.
Expand Down Expand Up @@ -2391,7 +2441,7 @@ struct TargetProtocolConformanceDescriptor final

private:
/// The protocol being conformed to.
RelativeIndirectablePointer<ProtocolDescriptor> Protocol;
TargetRelativeContextPointer<Runtime, TargetProtocolDescriptor> Protocol;

// Some description of the type that conforms to the protocol.
TargetTypeReference<Runtime> TypeRef;
Expand Down Expand Up @@ -2424,7 +2474,8 @@ struct TargetProtocolConformanceDescriptor final
return TypeRef.getTypeDescriptor(getTypeKind());
}

const TargetContextDescriptor<Runtime> **_getTypeDescriptorLocation() const {
TargetContextDescriptor<Runtime> * __ptrauth_swift_type_descriptor *
_getTypeDescriptorLocation() const {
if (getTypeKind() != TypeReferenceKind::IndirectTypeDescriptor)
return nullptr;
return TypeRef.IndirectTypeDescriptor.get();
Expand Down Expand Up @@ -4490,11 +4541,20 @@ struct DynamicReplacementChainEntry {
struct DynamicReplacementKey {
RelativeDirectPointer<DynamicReplacementChainEntry, false> root;
uint32_t flags;

uint16_t getExtraDiscriminator() const {
return flags & 0x0000FFFF;
}
};

/// A record describing a dynamic function replacement.
class DynamicReplacementDescriptor {
RelativeIndirectablePointer<DynamicReplacementKey, false> replacedFunctionKey;
RelativeIndirectablePointer<
const DynamicReplacementKey, false, int32_t,
TargetSignedPointer<InProcess,
DynamicReplacementKey *
__ptrauth_swift_dynamic_replacement_key>>
replacedFunctionKey;
RelativeDirectPointer<void, false> replacementFunction;
RelativeDirectPointer<DynamicReplacementChainEntry, false> chainEntry;
uint32_t flags;
Expand Down
Loading