Skip to content

[5.0][runtime] Reinstate TwoWordPair hack for swiftcall returns. #14129

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 1 commit into from
Jan 24, 2018
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
6 changes: 2 additions & 4 deletions include/swift/Runtime/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@
// convention.
#define SWIFT_LLVM_CC(CC) SWIFT_LLVM_CC_##CC

// Currently, RuntimeFunctions.def uses the following calling conventions:
// DefaultCC, RegisterPreservingCC, SwiftCC.
// Currently, RuntimeFunction.def uses the following calling conventions:
// DefaultCC, RegisterPreservingCC.
// If new runtime calling conventions are added later, they need to be mapped
// here to something appropriate.

Expand All @@ -135,8 +135,6 @@
#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

#define SWIFT_LLVM_CC_SwiftCC llvm::CallingConv::Swift
Expand Down
81 changes: 66 additions & 15 deletions include/swift/Runtime/HeapObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,66 @@ HeapObject *swift_initStaticObject(HeapMetadata const *metadata,
SWIFT_RUNTIME_EXPORT
void swift_verifyEndOfLifetime(HeapObject *object);

struct BoxPair {
HeapObject *object;
OpaqueValue *buffer;
/// 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://36755525 clang miscompiles swiftcall functions
// 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
};

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
Expand All @@ -109,19 +165,19 @@ struct BoxPair {
/// 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_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);
SWIFT_RUNTIME_EXPORT
BoxPair::Return (*_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_CC(swift) SWIFT_RUNTIME_EXPORT
BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
SWIFT_RUNTIME_EXPORT
BoxPair::Return swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
size_t alignMask);

/// Returns the address of a heap object representing all empty box types.
Expand Down Expand Up @@ -1186,16 +1242,11 @@ 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
TypeNamePair
TwoWordPair<const char *, uintptr_t>::Return
swift_getTypeName(const Metadata *type, bool qualified);

} // end namespace swift
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Runtime/InstrumentsSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ HeapObject *(*_swift_allocObject)(HeapMetadata const *metadata,
size_t requiredAlignmentMask);

SWIFT_RUNTIME_EXPORT
BoxPair (*swift_allocBox)(Metadata const *type);
BoxPair::Return (*_swift_allocBox)(Metadata const *type);

SWIFT_RUNTIME_EXPORT
HeapObject *(*_swift_retain)(HeapObject *object);
Expand Down
6 changes: 3 additions & 3 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@
#endif

FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(AllocBox, swift_allocBox,
_swift_allocBox, _swift_allocBox_, SwiftCC,
_swift_allocBox, _swift_allocBox_, DefaultCC,
RETURNS(RefCountedPtrTy, OpaquePtrTy),
ARGS(TypeMetadataPtrTy),
ATTRS(NoUnwind))

// BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata *type, size_t alignMask);
FUNCTION(MakeBoxUnique,
swift_makeBoxUnique,
SwiftCC,
DefaultCC,
RETURNS(RefCountedPtrTy, OpaquePtrTy),
ARGS(OpaquePtrTy, TypeMetadataPtrTy, SizeTy),
ATTRS(NoUnwind))
Expand Down Expand Up @@ -1318,7 +1318,7 @@ FUNCTION(DeletedMethodError, swift_deletedMethodError, C_CC,
ARGS(),
ATTRS(NoUnwind))

FUNCTION(AllocError, swift_allocError, SwiftCC,
FUNCTION(AllocError, swift_allocError, C_CC,
RETURNS(ErrorPtrTy, OpaquePtrTy),
ARGS(TypeMetadataPtrTy, WitnessTablePtrTy, OpaquePtrTy, Int1Ty),
ATTRS(NoUnwind))
Expand Down
4 changes: 0 additions & 4 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,10 +609,6 @@ 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), \
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/SDK/Foundation/CheckClass.mm
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ static void logIfFirstOccurrence(Class objcClass, void (^log)(void)) {
template <size_t N>
StringRefLite(const char (&staticStr)[N]) : data(staticStr), length(N) {}

StringRefLite(swift::TypeNamePair rawValue)
: data(rawValue.data),
length(rawValue.length){}
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){}

NS_RETURNS_RETAINED
NSString *newNSStringNoCopy() const {
Expand Down
13 changes: 7 additions & 6 deletions stdlib/public/runtime/Casting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ std::string swift::nameForMetadata(const Metadata *type,
return result;
}

TypeNamePair
TwoWordPair<const char *, uintptr_t>::Return
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;
Expand All @@ -131,7 +132,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
auto found = cache.find(key);
if (found != cache.end()) {
auto result = found->second;
return TypeNamePair{result.first, result.second};
return Pair{result.first, result.second};
}
}

Expand All @@ -144,7 +145,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
auto found = cache.find(key);
if (found != cache.end()) {
auto result = found->second;
return TypeNamePair{result.first, result.second};
return Pair{result.first, result.second};
}

// Build the metadata name.
Expand All @@ -156,7 +157,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
result[size] = 0;

cache.insert({key, {result, size}});
return TypeNamePair{result, size};
return Pair{result, size};
}
}

Expand Down Expand Up @@ -954,7 +955,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
(canConsumeDynamicValue && (flags & DynamicCastFlags::TakeOnSuccess));
BoxPair destBox = swift_allocError(srcDynamicType, errorWitness,
srcDynamicValue, isTake);
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.object);
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.first);
maybeDeallocateSource(true);
return true;
}
Expand Down Expand Up @@ -1976,7 +1977,7 @@ static id dynamicCastValueToNSError(OpaqueValue *src,

BoxPair errorBox = swift_allocError(srcType, srcErrorWitness, src,
/*isTake*/ flags & DynamicCastFlags::TakeOnSuccess);
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.object);
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.first);
}

#endif
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/runtime/ErrorObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ 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_CC(swift) SWIFT_RUNTIME_STDLIB_API
BoxPair swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *value, bool isTake);
SWIFT_RUNTIME_STDLIB_API
BoxPair::Return swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *value, bool isTake);

/// Deallocate an error object whose contained object has already been
/// destroyed.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/runtime/ErrorObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static Class getSwiftNativeNSErrorClass() {
}

/// Allocate a catchable error object.
BoxPair
BoxPair::Return
swift::swift_allocError(const Metadata *type,
const WitnessTable *errorConformance,
OpaqueValue *initialValue,
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/runtime/ErrorObjectNative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static const FullMetadata<HeapMetadata> ErrorMetadata{
Metadata{MetadataKind::ErrorObject},
};

BoxPair
BoxPair::Return
swift::swift_allocError(const swift::Metadata *type,
const swift::WitnessTable *errorConformance,
OpaqueValue *initialValue,
Expand Down
10 changes: 5 additions & 5 deletions stdlib/public/runtime/HeapObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ class BoxCacheEntry {

static SimpleGlobalCache<BoxCacheEntry> Boxes;

BoxPair swift::swift_allocBox(const Metadata *type) {
BoxPair::Return swift::swift_allocBox(const Metadata *type) {
return SWIFT_RT_ENTRY_REF(swift_allocBox)(type);
}

BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
BoxPair::Return 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]);
Expand All @@ -235,8 +235,8 @@ BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
auto *oldObjectAddr = reinterpret_cast<OpaqueValue *>(
reinterpret_cast<char *>(box) + headerOffset);
// Copy the data.
type->vw_initializeWithCopy(refAndObjectAddr.buffer, oldObjectAddr);
inlineBuffer->PrivateData[0] = refAndObjectAddr.object;
type->vw_initializeWithCopy(refAndObjectAddr.second, oldObjectAddr);
inlineBuffer->PrivateData[0] = refAndObjectAddr.first;
// Release ownership of the old box.
swift_release(box);
return refAndObjectAddr;
Expand All @@ -250,7 +250,7 @@ BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,

SWIFT_RT_ENTRY_IMPL_VISIBILITY
extern "C"
BoxPair SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
BoxPair::Return SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
// Get the heap metadata for the box.
auto metadata = &Boxes.getOrInsert(type).first->Data;

Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/runtime/Metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,8 +592,8 @@ static OpaqueValue *tuple_allocateBuffer(ValueBuffer *buffer,
if (IsInline)
return reinterpret_cast<OpaqueValue*>(buffer);
BoxPair refAndValueAddr(swift_allocBox(metatype));
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.object;
return refAndValueAddr.buffer;
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.first;
return refAndValueAddr.second;
}

/// Generic tuple value witness for 'destroy'.
Expand Down Expand Up @@ -2616,8 +2616,8 @@ template <> OpaqueValue *Metadata::allocateBoxForExistentialIn(ValueBuffer *buff

// Allocate the box.
BoxPair refAndValueAddr(swift_allocBox(this));
buffer->PrivateData[0] = refAndValueAddr.object;
return refAndValueAddr.buffer;
buffer->PrivateData[0] = refAndValueAddr.first;
return refAndValueAddr.second;
}

template <> OpaqueValue *Metadata::allocateBufferIn(ValueBuffer *buffer) const {
Expand Down
7 changes: 4 additions & 3 deletions stdlib/public/runtime/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ const {
// array of witness tables to pass along to the accessor.

// Pretty-print the type name.
auto typeNamePair = swift_getTypeName(type, /*qualified=*/true);
std::string typeName(typeNamePair.data,
typeNamePair.data + typeNamePair.length);
auto typeNamePair = TwoWordPair<const char *, uintptr_t>(
swift_getTypeName(type, /*qualified=*/true));
std::string typeName(typeNamePair.first,
typeNamePair.first + typeNamePair.second);

// Demangle the protocol name.
DemangleOptions options;
Expand Down
16 changes: 8 additions & 8 deletions stdlib/public/runtime/Reflection.mm
Original file line number Diff line number Diff line change
Expand Up @@ -668,23 +668,23 @@ void swift_EnumMirror_subscript(String *outString,
BoxPair pair = swift_allocBox(boxType);

type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
boxType->vw_initializeWithCopy(pair.second, const_cast<OpaqueValue *>(value));
type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
(int) (tag - Description.getNumPayloadCases()));

#ifndef SWIFT_RUNTIME_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
swift_release(owner);
#endif

owner = pair.object;
value = pair.buffer;
owner = pair.first;
value = pair.second;

// 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.object);
swift_release(pair.first);
}

new (outString) String(getFieldName(Description.CaseNames, tag));
Expand Down Expand Up @@ -1086,12 +1086,12 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
BoxPair box = swift_allocBox(T);

if (take)
T->vw_initializeWithTake(box.buffer, value);
T->vw_initializeWithTake(box.second, value);
else
T->vw_initializeWithCopy(box.buffer, value);
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);
T->vw_initializeWithCopy(box.second, value);
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second);

Data = {box.object, box.buffer, T};
Data = {box.first, box.second, T};
}

/// MagicMirror ownership-sharing subvalue constructor.
Expand Down
Loading