mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[runtime] Remove TwoWordPair and use the Swift calling convention instead. (#13299)
This commit is contained in:
committed by
Greg Parker
parent
f767040b4a
commit
c5bf2ec553
@@ -121,8 +121,8 @@
|
||||
// convention.
|
||||
#define SWIFT_LLVM_CC(CC) SWIFT_LLVM_CC_##CC
|
||||
|
||||
// Currently, RuntimeFunction.def uses the following calling conventions:
|
||||
// DefaultCC, RegisterPreservingCC.
|
||||
// Currently, RuntimeFunctions.def uses the following calling conventions:
|
||||
// DefaultCC, RegisterPreservingCC, SwiftCC.
|
||||
// If new runtime calling conventions are added later, they need to be mapped
|
||||
// here to something appropriate.
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
#define SWIFT_CC_DefaultCC_IMPL SWIFT_CC_c
|
||||
#define SWIFT_LLVM_CC_DefaultCC llvm::CallingConv::C
|
||||
|
||||
#define SWIFT_CC_SwiftCC SWIFT_CC_swift
|
||||
|
||||
#define SWIFT_LLVM_CC_RegisterPreservingCC llvm::CallingConv::PreserveMost
|
||||
|
||||
#if SWIFT_USE_SWIFTCALL
|
||||
|
||||
@@ -97,67 +97,11 @@ HeapObject *swift_initStaticObject(HeapMetadata const *metadata,
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_verifyEndOfLifetime(HeapObject *object);
|
||||
|
||||
/// A structure that's two pointers in size.
|
||||
///
|
||||
/// C functions can use the TwoWordPair::Return type to return a value in
|
||||
/// two registers, compatible with Swift's calling convention for tuples
|
||||
/// and structs of two word-sized elements.
|
||||
template<typename A, typename B>
|
||||
struct TwoWordPair {
|
||||
A first;
|
||||
B second;
|
||||
|
||||
TwoWordPair() = default;
|
||||
TwoWordPair(A first, B second);
|
||||
|
||||
// FIXME: rdar://16257592 arm codegen doesn't call swift_allocBox correctly.
|
||||
// Structs are returned indirectly on these platforms, but we want to return
|
||||
// in registers, so cram the result into an unsigned long long.
|
||||
// Use an enum class with implicit conversions so we don't dirty C callers
|
||||
// too much.
|
||||
#if __arm__ || __i386__ || defined(__CYGWIN__) || defined(_MSC_VER)
|
||||
#if defined(__CYGWIN__)
|
||||
enum class Return : unsigned __int128 {};
|
||||
#else
|
||||
enum class Return : unsigned long long {};
|
||||
#endif
|
||||
|
||||
operator Return() const {
|
||||
union {
|
||||
TwoWordPair value;
|
||||
Return mangled;
|
||||
} reinterpret = {*this};
|
||||
|
||||
return reinterpret.mangled;
|
||||
}
|
||||
|
||||
/*implicit*/ TwoWordPair(Return r) {
|
||||
union {
|
||||
Return mangled;
|
||||
TwoWordPair value;
|
||||
} reinterpret = {r};
|
||||
|
||||
*this = reinterpret.value;
|
||||
}
|
||||
#else
|
||||
using Return = TwoWordPair;
|
||||
#endif
|
||||
struct BoxPair {
|
||||
HeapObject *object;
|
||||
OpaqueValue *buffer;
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
inline TwoWordPair<A,B>::TwoWordPair(A first, B second)
|
||||
: first(first), second(second)
|
||||
{
|
||||
static_assert(sizeof(A) == sizeof(void*),
|
||||
"first type must be word-sized");
|
||||
static_assert(sizeof(B) == sizeof(void*),
|
||||
"second type must be word-sized");
|
||||
static_assert(alignof(TwoWordPair) == alignof(void*),
|
||||
"pair must be word-aligned");
|
||||
}
|
||||
|
||||
using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
|
||||
|
||||
/// Allocates a heap object that can contain a value of the given type.
|
||||
/// Returns a Box structure containing a HeapObject* pointer to the
|
||||
/// allocated object, and a pointer to the value inside the heap object.
|
||||
@@ -165,19 +109,19 @@ using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
|
||||
/// appropriate to store a value of the given type.
|
||||
/// The heap object has an initial retain count of 1, and its metadata is set
|
||||
/// such that destroying the heap object destroys the contained value.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
BoxPair::Return swift_allocBox(Metadata const *type);
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
|
||||
BoxPair swift_allocBox(Metadata const *type);
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
BoxPair::Return (*_swift_allocBox)(Metadata const *type);
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
|
||||
BoxPair (*_swift_allocBox)(Metadata const *type);
|
||||
|
||||
/// Performs a uniqueness check on the pointer to a box structure. If the check
|
||||
/// fails allocates a new box and stores the pointer in the buffer.
|
||||
///
|
||||
/// if (!isUnique(buffer[0]))
|
||||
/// buffer[0] = swift_allocBox(type)
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
BoxPair::Return swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
|
||||
BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
|
||||
size_t alignMask);
|
||||
|
||||
/// Returns the address of a heap object representing all empty box types.
|
||||
@@ -1242,11 +1186,16 @@ static inline bool swift_unknownUnownedIsEqual(UnownedReference *ref,
|
||||
|
||||
#endif /* SWIFT_OBJC_INTEROP */
|
||||
|
||||
struct TypeNamePair {
|
||||
const char *data;
|
||||
uintptr_t length;
|
||||
};
|
||||
|
||||
/// Return the name of a Swift type represented by a metadata object.
|
||||
/// func _getTypeName(_ type: Any.Type, qualified: Bool)
|
||||
/// -> (UnsafePointer<UInt8>, Int)
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
|
||||
TwoWordPair<const char *, uintptr_t>::Return
|
||||
TypeNamePair
|
||||
swift_getTypeName(const Metadata *type, bool qualified);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -26,7 +26,7 @@ HeapObject *(*_swift_allocObject)(HeapMetadata const *metadata,
|
||||
size_t requiredAlignmentMask);
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
BoxPair::Return (*_swift_allocBox)(Metadata const *type);
|
||||
BoxPair (*swift_allocBox)(Metadata const *type);
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
HeapObject *(*_swift_retain)(HeapObject *object);
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#endif
|
||||
|
||||
FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(AllocBox, swift_allocBox,
|
||||
_swift_allocBox, _swift_allocBox_, DefaultCC,
|
||||
_swift_allocBox, _swift_allocBox_, SwiftCC,
|
||||
RETURNS(RefCountedPtrTy, OpaquePtrTy),
|
||||
ARGS(TypeMetadataPtrTy),
|
||||
ATTRS(NoUnwind))
|
||||
@@ -58,7 +58,7 @@ FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(AllocBox, swift_allocBox,
|
||||
// BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata *type, size_t alignMask);
|
||||
FUNCTION(MakeBoxUnique,
|
||||
swift_makeBoxUnique,
|
||||
DefaultCC,
|
||||
SwiftCC,
|
||||
RETURNS(RefCountedPtrTy, OpaquePtrTy),
|
||||
ARGS(OpaquePtrTy, TypeMetadataPtrTy, SizeTy),
|
||||
ATTRS(NoUnwind))
|
||||
@@ -1332,7 +1332,7 @@ FUNCTION(DeletedMethodError, swift_deletedMethodError, C_CC,
|
||||
ARGS(),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
FUNCTION(AllocError, swift_allocError, C_CC,
|
||||
FUNCTION(AllocError, swift_allocError, SwiftCC,
|
||||
RETURNS(ErrorPtrTy, OpaquePtrTy),
|
||||
ARGS(TypeMetadataPtrTy, WitnessTablePtrTy, OpaquePtrTy, Int1Ty),
|
||||
ATTRS(NoUnwind))
|
||||
|
||||
@@ -610,6 +610,10 @@ llvm::Constant *swift::getWrapperFn(llvm::Module &Module,
|
||||
RETURNS, ARGS, ATTRS) \
|
||||
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
|
||||
|
||||
#define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_SwiftCC(ID, NAME, SYMBOL, CC, \
|
||||
RETURNS, ARGS, ATTRS) \
|
||||
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
|
||||
|
||||
#define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_RegisterPreservingCC( \
|
||||
ID, NAME, SYMBOL, CC, RETURNS, ARGS, ATTRS) \
|
||||
FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, SYMBOL, CC, QUOTE(RETURNS), \
|
||||
|
||||
@@ -59,9 +59,9 @@ namespace {
|
||||
template <size_t N>
|
||||
StringRefLite(const char (&staticStr)[N]) : data(staticStr), length(N) {}
|
||||
|
||||
StringRefLite(swift::TwoWordPair<const char *, uintptr_t>::Return rawValue)
|
||||
: data(swift::TwoWordPair<const char *, uintptr_t>(rawValue).first),
|
||||
length(swift::TwoWordPair<const char *, uintptr_t>(rawValue).second){}
|
||||
StringRefLite(swift::TypeNamePair rawValue)
|
||||
: data(rawValue.data),
|
||||
length(rawValue.length){}
|
||||
|
||||
NS_RETURNS_RETAINED
|
||||
NSString *newNSStringNoCopy() const {
|
||||
|
||||
@@ -113,9 +113,8 @@ std::string swift::nameForMetadata(const Metadata *type,
|
||||
return result;
|
||||
}
|
||||
|
||||
TwoWordPair<const char *, uintptr_t>::Return
|
||||
TypeNamePair
|
||||
swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
using Pair = TwoWordPair<const char *, uintptr_t>;
|
||||
using Key = llvm::PointerIntPair<const Metadata *, 1, bool>;
|
||||
|
||||
static StaticReadWriteLock TypeNameCacheLock;
|
||||
@@ -132,7 +131,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
auto found = cache.find(key);
|
||||
if (found != cache.end()) {
|
||||
auto result = found->second;
|
||||
return Pair{result.first, result.second};
|
||||
return TypeNamePair{result.first, result.second};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +144,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
auto found = cache.find(key);
|
||||
if (found != cache.end()) {
|
||||
auto result = found->second;
|
||||
return Pair{result.first, result.second};
|
||||
return TypeNamePair{result.first, result.second};
|
||||
}
|
||||
|
||||
// Build the metadata name.
|
||||
@@ -157,7 +156,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
|
||||
result[size] = 0;
|
||||
|
||||
cache.insert({key, {result, size}});
|
||||
return Pair{result, size};
|
||||
return TypeNamePair{result, size};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,7 +954,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
|
||||
(canConsumeDynamicValue && (flags & DynamicCastFlags::TakeOnSuccess));
|
||||
BoxPair destBox = swift_allocError(srcDynamicType, errorWitness,
|
||||
srcDynamicValue, isTake);
|
||||
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.first);
|
||||
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.object);
|
||||
maybeDeallocateSource(true);
|
||||
return true;
|
||||
}
|
||||
@@ -1977,7 +1976,7 @@ static id dynamicCastValueToNSError(OpaqueValue *src,
|
||||
|
||||
BoxPair errorBox = swift_allocError(srcType, srcErrorWitness, src,
|
||||
/*isTake*/ flags & DynamicCastFlags::TakeOnSuccess);
|
||||
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.first);
|
||||
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.object);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -171,8 +171,8 @@ struct SwiftError : SwiftErrorHeader {
|
||||
/// copied (or taken if \c isTake is true) into the newly-allocated error box.
|
||||
/// If value is null, the box's contents will be left uninitialized, and
|
||||
/// \c isTake should be false.
|
||||
SWIFT_RUNTIME_STDLIB_API
|
||||
BoxPair::Return swift_allocError(const Metadata *type,
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
|
||||
BoxPair swift_allocError(const Metadata *type,
|
||||
const WitnessTable *errorConformance,
|
||||
OpaqueValue *value, bool isTake);
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ static Class getSwiftNativeNSErrorClass() {
|
||||
}
|
||||
|
||||
/// Allocate a catchable error object.
|
||||
BoxPair::Return
|
||||
BoxPair
|
||||
swift::swift_allocError(const Metadata *type,
|
||||
const WitnessTable *errorConformance,
|
||||
OpaqueValue *initialValue,
|
||||
|
||||
@@ -64,7 +64,7 @@ static const FullMetadata<HeapMetadata> ErrorMetadata{
|
||||
Metadata{MetadataKind::ErrorObject},
|
||||
};
|
||||
|
||||
BoxPair::Return
|
||||
BoxPair
|
||||
swift::swift_allocError(const swift::Metadata *type,
|
||||
const swift::WitnessTable *errorConformance,
|
||||
OpaqueValue *initialValue,
|
||||
|
||||
@@ -203,11 +203,11 @@ public:
|
||||
|
||||
static SimpleGlobalCache<BoxCacheEntry> Boxes;
|
||||
|
||||
BoxPair::Return swift::swift_allocBox(const Metadata *type) {
|
||||
BoxPair swift::swift_allocBox(const Metadata *type) {
|
||||
return SWIFT_RT_ENTRY_REF(swift_allocBox)(type);
|
||||
}
|
||||
|
||||
BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
|
||||
BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
|
||||
size_t alignMask) {
|
||||
auto *inlineBuffer = reinterpret_cast<ValueBuffer*>(buffer);
|
||||
HeapObject *box = reinterpret_cast<HeapObject *>(inlineBuffer->PrivateData[0]);
|
||||
@@ -219,8 +219,8 @@ BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *
|
||||
auto *oldObjectAddr = reinterpret_cast<OpaqueValue *>(
|
||||
reinterpret_cast<char *>(box) + headerOffset);
|
||||
// Copy the data.
|
||||
type->vw_initializeWithCopy(refAndObjectAddr.second, oldObjectAddr);
|
||||
inlineBuffer->PrivateData[0] = refAndObjectAddr.first;
|
||||
type->vw_initializeWithCopy(refAndObjectAddr.buffer, oldObjectAddr);
|
||||
inlineBuffer->PrivateData[0] = refAndObjectAddr.object;
|
||||
// Release ownership of the old box.
|
||||
swift_release(box);
|
||||
return refAndObjectAddr;
|
||||
@@ -234,7 +234,7 @@ BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *
|
||||
|
||||
SWIFT_RT_ENTRY_IMPL_VISIBILITY
|
||||
extern "C"
|
||||
BoxPair::Return SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
|
||||
BoxPair SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
|
||||
// Get the heap metadata for the box.
|
||||
auto metadata = &Boxes.getOrInsert(type).first->Data;
|
||||
|
||||
|
||||
@@ -636,8 +636,8 @@ static OpaqueValue *tuple_allocateBuffer(ValueBuffer *buffer,
|
||||
if (IsInline)
|
||||
return reinterpret_cast<OpaqueValue*>(buffer);
|
||||
BoxPair refAndValueAddr(swift_allocBox(metatype));
|
||||
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.first;
|
||||
return refAndValueAddr.second;
|
||||
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.object;
|
||||
return refAndValueAddr.buffer;
|
||||
}
|
||||
|
||||
/// Generic tuple value witness for 'destroy'.
|
||||
@@ -2542,8 +2542,8 @@ template <> OpaqueValue *Metadata::allocateBoxForExistentialIn(ValueBuffer *buff
|
||||
|
||||
// Allocate the box.
|
||||
BoxPair refAndValueAddr(swift_allocBox(this));
|
||||
buffer->PrivateData[0] = refAndValueAddr.first;
|
||||
return refAndValueAddr.second;
|
||||
buffer->PrivateData[0] = refAndValueAddr.object;
|
||||
return refAndValueAddr.buffer;
|
||||
}
|
||||
|
||||
template <> OpaqueValue *Metadata::allocateBufferIn(ValueBuffer *buffer) const {
|
||||
|
||||
@@ -633,21 +633,21 @@ void swift_EnumMirror_subscript(String *outString,
|
||||
BoxPair pair = swift_allocBox(boxType);
|
||||
|
||||
type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
|
||||
boxType->vw_initializeWithCopy(pair.second, const_cast<OpaqueValue *>(value));
|
||||
boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
|
||||
type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
|
||||
(int) (tag - Description.getNumPayloadCases()));
|
||||
|
||||
swift_release(owner);
|
||||
|
||||
owner = pair.first;
|
||||
value = pair.second;
|
||||
owner = pair.object;
|
||||
value = pair.buffer;
|
||||
|
||||
// If the payload is indirect, we need to jump through the box to get it.
|
||||
if (indirect) {
|
||||
owner = *reinterpret_cast<HeapObject * const *>(value);
|
||||
value = swift_projectBox(const_cast<HeapObject *>(owner));
|
||||
swift_retain(owner);
|
||||
swift_release(pair.first);
|
||||
swift_release(pair.object);
|
||||
}
|
||||
|
||||
new (outString) String(getFieldName(Description.CaseNames, tag));
|
||||
@@ -1035,12 +1035,12 @@ MagicMirror::MagicMirror(OpaqueValue *value, const Metadata *T,
|
||||
BoxPair box = swift_allocBox(T);
|
||||
|
||||
if (take)
|
||||
T->vw_initializeWithTake(box.second, value);
|
||||
T->vw_initializeWithTake(box.buffer, value);
|
||||
else
|
||||
T->vw_initializeWithCopy(box.second, value);
|
||||
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second);
|
||||
T->vw_initializeWithCopy(box.buffer, value);
|
||||
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);
|
||||
|
||||
Data = {box.first, box.second, T};
|
||||
Data = {box.object, box.buffer, T};
|
||||
}
|
||||
|
||||
/// MagicMirror ownership-sharing subvalue constructor.
|
||||
|
||||
@@ -1423,10 +1423,13 @@ bool swift::swift_isUniquelyReferencedOrPinned_nonNull_native(
|
||||
return object->refCounts.isUniquelyReferencedOrPinned();
|
||||
}
|
||||
|
||||
using ClassExtents = TwoWordPair<size_t, size_t>;
|
||||
struct ClassExtents {
|
||||
size_t negative;
|
||||
size_t positive;
|
||||
};
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
ClassExtents::Return
|
||||
ClassExtents
|
||||
_getSwiftClassInstanceExtents(const Metadata *c) {
|
||||
assert(c && c->isClassObject());
|
||||
auto metaData = c->getClassObject();
|
||||
@@ -1439,7 +1442,7 @@ _getSwiftClassInstanceExtents(const Metadata *c) {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
ClassExtents::Return
|
||||
ClassExtents
|
||||
_getObjCClassInstanceExtents(const ClassMetadata* c) {
|
||||
// Pure ObjC classes never have negative extents.
|
||||
if (c->isPureObjC())
|
||||
|
||||
@@ -366,10 +366,10 @@ static NSString *getValueDescription(_SwiftValue *self) {
|
||||
return getSwiftValueTypeMetadata(self);
|
||||
}
|
||||
- (NSString *)_swiftTypeName {
|
||||
TwoWordPair<const char *, uintptr_t> typeName
|
||||
TypeNamePair typeName
|
||||
= swift_getTypeName(getSwiftValueTypeMetadata(self), true);
|
||||
|
||||
return [NSString stringWithUTF8String: typeName.first];
|
||||
return [NSString stringWithUTF8String: typeName.data];
|
||||
}
|
||||
- (const OpaqueValue *)_swiftValue {
|
||||
return getValueFromSwiftValue(self).second;
|
||||
|
||||
@@ -21,7 +21,7 @@ entry(%e : $Error):
|
||||
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.Error)
|
||||
sil @alloc_boxed_existential : $@convention(thin) <T: Error> (@in T) -> @owned Error {
|
||||
entry(%x : $*T):
|
||||
// CHECK: [[BOX_PAIR:%.*]] = call { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* %T, i8** %T.Error, %swift.opaque* null, i1 false)
|
||||
// CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* %T, i8** %T.Error, %swift.opaque* null, i1 false)
|
||||
// CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
|
||||
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
|
||||
%b = alloc_existential_box $Error, $T
|
||||
@@ -40,7 +40,7 @@ struct SomeError: Error {
|
||||
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential_concrete
|
||||
sil @alloc_boxed_existential_concrete : $@convention(thin) (@owned SomeError) -> @owned Error {
|
||||
entry(%x : $SomeError):
|
||||
// CHECK: [[BOX_PAIR:%.*]] = call { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @_T017boxed_existential9SomeErrorVMf, {{.*}}, i8** {{%.*|@_T017boxed_existential9SomeErrorVs0D0AAWP}}, %swift.opaque* null, i1 false)
|
||||
// CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @_T017boxed_existential9SomeErrorVMf, {{.*}}, i8** {{%.*|@_T017boxed_existential9SomeErrorVs0D0AAWP}}, %swift.opaque* null, i1 false)
|
||||
// CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
|
||||
// CHECK: [[OPAQUE_ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
|
||||
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OPAQUE_ADDR]] to %T17boxed_existential9SomeErrorV*
|
||||
|
||||
@@ -49,7 +49,7 @@ func b<T : Ordinable>(seq seq: T) -> (Int) -> Int {
|
||||
func captures_tuple<T, U>(x x: (T, U)) -> () -> (T, U) {
|
||||
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getTupleTypeMetadata2(%swift.type* %T, %swift.type* %U, i8* null, i8** null)
|
||||
// CHECK-NOT: @swift_getTupleTypeMetadata2
|
||||
// CHECK: [[BOX:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
|
||||
// CHECK: [[BOX:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
|
||||
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[BOX]], 1
|
||||
// CHECK: bitcast %swift.opaque* [[ADDR]] to <{}>*
|
||||
return {x}
|
||||
|
||||
@@ -54,7 +54,7 @@ entry(%0 : $*T):
|
||||
// CHECK: ret %swift.opaque* [[EXISTENTIAL_BUFFER_OPAQUE]]
|
||||
//
|
||||
// CHECK:allocateBox:
|
||||
// CHECK: [[CALL:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METATYPE]])
|
||||
// CHECK: [[CALL:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METATYPE]])
|
||||
// CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 0
|
||||
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 1
|
||||
// CHECK: [[ADDR_IN_BUFFER:%.*]] = bitcast [{{(24|12)}} x i8]* [[EXISTENTIAL_BUFFER]] to %swift.refcounted**
|
||||
@@ -221,7 +221,7 @@ bb0(%0 : $*Existential):
|
||||
// CHECK: boxed:
|
||||
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
|
||||
// CHECK: [[OPAQUE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
|
||||
// CHECK: [[REFANDADDR:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
|
||||
// CHECK: [[REFANDADDR:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
|
||||
// CHECK: [[REF:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 0
|
||||
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 1
|
||||
// CHECK: ret %swift.opaque* [[ADDR]]
|
||||
|
||||
@@ -121,7 +121,7 @@ sil @take_t : $@convention(thin) <T> (@in T) -> ()
|
||||
sil @dyn_box_a : $@convention(thin) <T> () -> () {
|
||||
entry:
|
||||
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T011typed_boxes3DynVMa(%swift.type* %T)
|
||||
// CHECK: [[ALLOC:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
|
||||
// CHECK: [[ALLOC:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
|
||||
// CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 0
|
||||
// CHECK: [[PTR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 1
|
||||
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Dyn<T>>
|
||||
@@ -138,7 +138,7 @@ entry:
|
||||
// CHECK-LABEL: define{{( protected)?}} swiftcc void @dyn_box_b
|
||||
sil @dyn_box_b : $@convention(thin) <T> () -> () {
|
||||
entry:
|
||||
// CHECK: [[ALLOC:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* %T)
|
||||
// CHECK: [[ALLOC:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* %T)
|
||||
// CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 0
|
||||
// CHECK: [[PTR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 1
|
||||
%a = alloc_box $<τ_0_0> { var τ_0_0 } <T>
|
||||
|
||||
@@ -1222,23 +1222,23 @@ TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_indirect) {
|
||||
Metadata *metadata2 = &testMetadata2.base;
|
||||
|
||||
auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
|
||||
swift_retain(refAndObjectAddr.first);
|
||||
swift_retain(refAndObjectAddr.object);
|
||||
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
|
||||
struct {
|
||||
ValueBuffer buffer;
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
} existBox{{{refAndObjectAddr.object, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr.object), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_indirect) {
|
||||
@@ -1258,23 +1258,23 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_indirect) {
|
||||
Metadata *metadata2 = &testMetadata2.base;
|
||||
|
||||
auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
|
||||
swift_retain(refAndObjectAddr.first);
|
||||
swift_retain(refAndObjectAddr.object);
|
||||
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
|
||||
struct {
|
||||
ValueBuffer buffer;
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
} existBox{{{refAndObjectAddr.object, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr.object), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod_indirect) {
|
||||
@@ -1299,15 +1299,15 @@ TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod_indirect) {
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_assignWithTake_pod_indirect) {
|
||||
@@ -1332,15 +1332,15 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_pod_indirect) {
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_pod) {
|
||||
@@ -1361,13 +1361,13 @@ TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_pod) {
|
||||
|
||||
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
|
||||
void *someAddr = &anyVWT;
|
||||
swift_retain(refAndObjectAddr2.first);
|
||||
swift_retain(refAndObjectAddr2.object);
|
||||
struct {
|
||||
ValueBuffer buffer;
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
@@ -1377,7 +1377,7 @@ TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_pod) {
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_pod) {
|
||||
@@ -1398,13 +1398,13 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_pod) {
|
||||
|
||||
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
|
||||
void *someAddr = &anyVWT;
|
||||
swift_retain(refAndObjectAddr2.first);
|
||||
swift_retain(refAndObjectAddr2.object);
|
||||
struct {
|
||||
ValueBuffer buffer;
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
@@ -1414,7 +1414,7 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_pod) {
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_initWithCopy_pod) {
|
||||
@@ -1507,15 +1507,15 @@ TEST(TestOpaqueExistentialBox, test_initWithCopy_indirect) {
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->initializeWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
|
||||
}
|
||||
|
||||
TEST(TestOpaqueExistentialBox, test_initWithTake_indirect) {
|
||||
@@ -1540,13 +1540,13 @@ TEST(TestOpaqueExistentialBox, test_initWithTake_indirect) {
|
||||
Metadata *type;
|
||||
uintptr_t canary;
|
||||
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
|
||||
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
|
||||
|
||||
anyVWT->initializeWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
|
||||
reinterpret_cast<OpaqueValue *>(&existBox2), any);
|
||||
|
||||
EXPECT_EQ(existBox.type, metadata2);
|
||||
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
|
||||
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
|
||||
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user