Skip to content

Commit 7b92247

Browse files
author
Greg Parker
authored
[runtime] Reinstate TwoWordPair hack for swiftcall returns. (#14079)
clang is miscompiling some swiftcall functions on armv7s. Stop using swiftcall in some places until it is fixed. Reverts c5bf2ec (#13299). rdar://35973477
1 parent 16c93f8 commit 7b92247

21 files changed

+151
-107
lines changed

include/swift/Runtime/Config.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@
125125
// convention.
126126
#define SWIFT_LLVM_CC(CC) SWIFT_LLVM_CC_##CC
127127

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

@@ -135,8 +135,6 @@
135135
#define SWIFT_CC_DefaultCC_IMPL SWIFT_CC_c
136136
#define SWIFT_LLVM_CC_DefaultCC llvm::CallingConv::C
137137

138-
#define SWIFT_CC_SwiftCC SWIFT_CC_swift
139-
140138
#define SWIFT_LLVM_CC_RegisterPreservingCC llvm::CallingConv::PreserveMost
141139

142140
#define SWIFT_LLVM_CC_SwiftCC llvm::CallingConv::Swift

include/swift/Runtime/HeapObject.h

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,66 @@ HeapObject *swift_initStaticObject(HeapMetadata const *metadata,
9797
SWIFT_RUNTIME_EXPORT
9898
void swift_verifyEndOfLifetime(HeapObject *object);
9999

100-
struct BoxPair {
101-
HeapObject *object;
102-
OpaqueValue *buffer;
100+
/// A structure that's two pointers in size.
101+
///
102+
/// C functions can use the TwoWordPair::Return type to return a value in
103+
/// two registers, compatible with Swift's calling convention for tuples
104+
/// and structs of two word-sized elements.
105+
template<typename A, typename B>
106+
struct TwoWordPair {
107+
A first;
108+
B second;
109+
110+
TwoWordPair() = default;
111+
TwoWordPair(A first, B second);
112+
113+
// FIXME: rdar://36755525 clang miscompiles swiftcall functions
114+
// Structs are returned indirectly on these platforms, but we want to return
115+
// in registers, so cram the result into an unsigned long long.
116+
// Use an enum class with implicit conversions so we don't dirty C callers
117+
// too much.
118+
#if __arm__ || __i386__ || defined(__CYGWIN__) || defined(_MSC_VER)
119+
#if defined(__CYGWIN__)
120+
enum class Return : unsigned __int128 {};
121+
#else
122+
enum class Return : unsigned long long {};
123+
#endif
124+
125+
operator Return() const {
126+
union {
127+
TwoWordPair value;
128+
Return mangled;
129+
} reinterpret = {*this};
130+
131+
return reinterpret.mangled;
132+
}
133+
134+
/*implicit*/ TwoWordPair(Return r) {
135+
union {
136+
Return mangled;
137+
TwoWordPair value;
138+
} reinterpret = {r};
139+
140+
*this = reinterpret.value;
141+
}
142+
#else
143+
using Return = TwoWordPair;
144+
#endif
103145
};
146+
147+
template<typename A, typename B>
148+
inline TwoWordPair<A,B>::TwoWordPair(A first, B second)
149+
: first(first), second(second)
150+
{
151+
static_assert(sizeof(A) == sizeof(void*),
152+
"first type must be word-sized");
153+
static_assert(sizeof(B) == sizeof(void*),
154+
"second type must be word-sized");
155+
static_assert(alignof(TwoWordPair) == alignof(void*),
156+
"pair must be word-aligned");
157+
}
158+
159+
using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
104160

105161
/// Allocates a heap object that can contain a value of the given type.
106162
/// Returns a Box structure containing a HeapObject* pointer to the
@@ -109,19 +165,19 @@ struct BoxPair {
109165
/// appropriate to store a value of the given type.
110166
/// The heap object has an initial retain count of 1, and its metadata is set
111167
/// such that destroying the heap object destroys the contained value.
112-
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
113-
BoxPair swift_allocBox(Metadata const *type);
168+
SWIFT_RUNTIME_EXPORT
169+
BoxPair::Return swift_allocBox(Metadata const *type);
114170

115-
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
116-
BoxPair (*_swift_allocBox)(Metadata const *type);
171+
SWIFT_RUNTIME_EXPORT
172+
BoxPair::Return (*_swift_allocBox)(Metadata const *type);
117173

118174
/// Performs a uniqueness check on the pointer to a box structure. If the check
119175
/// fails allocates a new box and stores the pointer in the buffer.
120176
///
121177
/// if (!isUnique(buffer[0]))
122178
/// buffer[0] = swift_allocBox(type)
123-
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
124-
BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
179+
SWIFT_RUNTIME_EXPORT
180+
BoxPair::Return swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
125181
size_t alignMask);
126182

127183
/// Returns the address of a heap object representing all empty box types.
@@ -1186,16 +1242,11 @@ static inline bool swift_unknownUnownedIsEqual(UnownedReference *ref,
11861242

11871243
#endif /* SWIFT_OBJC_INTEROP */
11881244

1189-
struct TypeNamePair {
1190-
const char *data;
1191-
uintptr_t length;
1192-
};
1193-
11941245
/// Return the name of a Swift type represented by a metadata object.
11951246
/// func _getTypeName(_ type: Any.Type, qualified: Bool)
11961247
/// -> (UnsafePointer<UInt8>, Int)
11971248
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
1198-
TypeNamePair
1249+
TwoWordPair<const char *, uintptr_t>::Return
11991250
swift_getTypeName(const Metadata *type, bool qualified);
12001251

12011252
} // end namespace swift

include/swift/Runtime/InstrumentsSupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ HeapObject *(*_swift_allocObject)(HeapMetadata const *metadata,
2626
size_t requiredAlignmentMask);
2727

2828
SWIFT_RUNTIME_EXPORT
29-
BoxPair (*swift_allocBox)(Metadata const *type);
29+
BoxPair::Return (*_swift_allocBox)(Metadata const *type);
3030

3131
SWIFT_RUNTIME_EXPORT
3232
HeapObject *(*_swift_retain)(HeapObject *object);

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@
5050
#endif
5151

5252
FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(AllocBox, swift_allocBox,
53-
_swift_allocBox, _swift_allocBox_, SwiftCC,
53+
_swift_allocBox, _swift_allocBox_, DefaultCC,
5454
RETURNS(RefCountedPtrTy, OpaquePtrTy),
5555
ARGS(TypeMetadataPtrTy),
5656
ATTRS(NoUnwind))
5757

5858
// BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata *type, size_t alignMask);
5959
FUNCTION(MakeBoxUnique,
6060
swift_makeBoxUnique,
61-
SwiftCC,
61+
DefaultCC,
6262
RETURNS(RefCountedPtrTy, OpaquePtrTy),
6363
ARGS(OpaquePtrTy, TypeMetadataPtrTy, SizeTy),
6464
ATTRS(NoUnwind))
@@ -1334,7 +1334,7 @@ FUNCTION(DeletedMethodError, swift_deletedMethodError, C_CC,
13341334
ARGS(),
13351335
ATTRS(NoUnwind))
13361336

1337-
FUNCTION(AllocError, swift_allocError, SwiftCC,
1337+
FUNCTION(AllocError, swift_allocError, C_CC,
13381338
RETURNS(ErrorPtrTy, OpaquePtrTy),
13391339
ARGS(TypeMetadataPtrTy, WitnessTablePtrTy, OpaquePtrTy, Int1Ty),
13401340
ATTRS(NoUnwind))

lib/IRGen/IRGenModule.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,6 @@ llvm::Constant *swift::getWrapperFn(llvm::Module &Module,
635635
RETURNS, ARGS, ATTRS) \
636636
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
637637

638-
#define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_SwiftCC(ID, NAME, SYMBOL, CC, \
639-
RETURNS, ARGS, ATTRS) \
640-
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
641-
642638
#define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_RegisterPreservingCC( \
643639
ID, NAME, SYMBOL, CC, RETURNS, ARGS, ATTRS) \
644640
FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, SYMBOL, CC, QUOTE(RETURNS), \

stdlib/public/SDK/Foundation/CheckClass.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ static void logIfFirstOccurrence(Class objcClass, void (^log)(void)) {
5959
template <size_t N>
6060
StringRefLite(const char (&staticStr)[N]) : data(staticStr), length(N) {}
6161

62-
StringRefLite(swift::TypeNamePair rawValue)
63-
: data(rawValue.data),
64-
length(rawValue.length){}
62+
StringRefLite(swift::TwoWordPair<const char *, uintptr_t>::Return rawValue)
63+
: data(swift::TwoWordPair<const char *, uintptr_t>(rawValue).first),
64+
length(swift::TwoWordPair<const char *, uintptr_t>(rawValue).second){}
6565

6666
NS_RETURNS_RETAINED
6767
NSString *newNSStringNoCopy() const {

stdlib/public/runtime/Casting.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ std::string swift::nameForMetadata(const Metadata *type,
113113
return result;
114114
}
115115

116-
TypeNamePair
116+
TwoWordPair<const char *, uintptr_t>::Return
117117
swift::swift_getTypeName(const Metadata *type, bool qualified) {
118+
using Pair = TwoWordPair<const char *, uintptr_t>;
118119
using Key = llvm::PointerIntPair<const Metadata *, 1, bool>;
119120

120121
static StaticReadWriteLock TypeNameCacheLock;
@@ -131,7 +132,7 @@ swift::swift_getTypeName(const Metadata *type, bool qualified) {
131132
auto found = cache.find(key);
132133
if (found != cache.end()) {
133134
auto result = found->second;
134-
return TypeNamePair{result.first, result.second};
135+
return Pair{result.first, result.second};
135136
}
136137
}
137138

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

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

158159
cache.insert({key, {result, size}});
159-
return TypeNamePair{result, size};
160+
return Pair{result, size};
160161
}
161162
}
162163

@@ -954,7 +955,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
954955
(canConsumeDynamicValue && (flags & DynamicCastFlags::TakeOnSuccess));
955956
BoxPair destBox = swift_allocError(srcDynamicType, errorWitness,
956957
srcDynamicValue, isTake);
957-
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.object);
958+
*destBoxAddr = reinterpret_cast<SwiftError*>(destBox.first);
958959
maybeDeallocateSource(true);
959960
return true;
960961
}
@@ -1976,7 +1977,7 @@ static id dynamicCastValueToNSError(OpaqueValue *src,
19761977

19771978
BoxPair errorBox = swift_allocError(srcType, srcErrorWitness, src,
19781979
/*isTake*/ flags & DynamicCastFlags::TakeOnSuccess);
1979-
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.object);
1980+
return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.first);
19801981
}
19811982

19821983
#endif

stdlib/public/runtime/ErrorObject.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ struct SwiftError : SwiftErrorHeader {
171171
/// copied (or taken if \c isTake is true) into the newly-allocated error box.
172172
/// If value is null, the box's contents will be left uninitialized, and
173173
/// \c isTake should be false.
174-
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
175-
BoxPair swift_allocError(const Metadata *type,
176-
const WitnessTable *errorConformance,
177-
OpaqueValue *value, bool isTake);
174+
SWIFT_RUNTIME_STDLIB_API
175+
BoxPair::Return swift_allocError(const Metadata *type,
176+
const WitnessTable *errorConformance,
177+
OpaqueValue *value, bool isTake);
178178

179179
/// Deallocate an error object whose contained object has already been
180180
/// destroyed.

stdlib/public/runtime/ErrorObject.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static Class getSwiftNativeNSErrorClass() {
161161
}
162162

163163
/// Allocate a catchable error object.
164-
BoxPair
164+
BoxPair::Return
165165
swift::swift_allocError(const Metadata *type,
166166
const WitnessTable *errorConformance,
167167
OpaqueValue *initialValue,

stdlib/public/runtime/ErrorObjectNative.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static const FullMetadata<HeapMetadata> ErrorMetadata{
6464
Metadata{MetadataKind::ErrorObject},
6565
};
6666

67-
BoxPair
67+
BoxPair::Return
6868
swift::swift_allocError(const swift::Metadata *type,
6969
const swift::WitnessTable *errorConformance,
7070
OpaqueValue *initialValue,

stdlib/public/runtime/HeapObject.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,11 @@ class BoxCacheEntry {
219219

220220
static SimpleGlobalCache<BoxCacheEntry> Boxes;
221221

222-
BoxPair swift::swift_allocBox(const Metadata *type) {
222+
BoxPair::Return swift::swift_allocBox(const Metadata *type) {
223223
return SWIFT_RT_ENTRY_REF(swift_allocBox)(type);
224224
}
225225

226-
BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
226+
BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
227227
size_t alignMask) {
228228
auto *inlineBuffer = reinterpret_cast<ValueBuffer*>(buffer);
229229
HeapObject *box = reinterpret_cast<HeapObject *>(inlineBuffer->PrivateData[0]);
@@ -235,8 +235,8 @@ BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
235235
auto *oldObjectAddr = reinterpret_cast<OpaqueValue *>(
236236
reinterpret_cast<char *>(box) + headerOffset);
237237
// Copy the data.
238-
type->vw_initializeWithCopy(refAndObjectAddr.buffer, oldObjectAddr);
239-
inlineBuffer->PrivateData[0] = refAndObjectAddr.object;
238+
type->vw_initializeWithCopy(refAndObjectAddr.second, oldObjectAddr);
239+
inlineBuffer->PrivateData[0] = refAndObjectAddr.first;
240240
// Release ownership of the old box.
241241
swift_release(box);
242242
return refAndObjectAddr;
@@ -250,7 +250,7 @@ BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
250250

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

stdlib/public/runtime/Metadata.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,8 @@ static OpaqueValue *tuple_allocateBuffer(ValueBuffer *buffer,
592592
if (IsInline)
593593
return reinterpret_cast<OpaqueValue*>(buffer);
594594
BoxPair refAndValueAddr(swift_allocBox(metatype));
595-
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.object;
596-
return refAndValueAddr.buffer;
595+
*reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.first;
596+
return refAndValueAddr.second;
597597
}
598598

599599
/// Generic tuple value witness for 'destroy'.
@@ -2638,8 +2638,8 @@ template <> OpaqueValue *Metadata::allocateBoxForExistentialIn(ValueBuffer *buff
26382638

26392639
// Allocate the box.
26402640
BoxPair refAndValueAddr(swift_allocBox(this));
2641-
buffer->PrivateData[0] = refAndValueAddr.object;
2642-
return refAndValueAddr.buffer;
2641+
buffer->PrivateData[0] = refAndValueAddr.first;
2642+
return refAndValueAddr.second;
26432643
}
26442644

26452645
template <> OpaqueValue *Metadata::allocateBufferIn(ValueBuffer *buffer) const {

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ ProtocolConformanceDescriptor::getWitnessTable(const Metadata *type) const {
123123
// array of witness tables to pass along to the accessor.
124124

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

130131
// Demangle the protocol name.
131132
DemangleOptions options;

stdlib/public/runtime/Reflection.mm

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -671,23 +671,23 @@ void swift_EnumMirror_subscript(String *outString,
671671
BoxPair pair = swift_allocBox(boxType);
672672

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

678678
#ifndef SWIFT_RUNTIME_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
679679
swift_release(owner);
680680
#endif
681681

682-
owner = pair.object;
683-
value = pair.buffer;
682+
owner = pair.first;
683+
value = pair.second;
684684

685685
// If the payload is indirect, we need to jump through the box to get it.
686686
if (indirect) {
687687
owner = *reinterpret_cast<HeapObject * const *>(value);
688688
value = swift_projectBox(const_cast<HeapObject *>(owner));
689689
swift_retain(owner);
690-
swift_release(pair.object);
690+
swift_release(pair.first);
691691
}
692692

693693
new (outString) String(getFieldName(Description.CaseNames, tag));
@@ -1089,12 +1089,12 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
10891089
BoxPair box = swift_allocBox(T);
10901090

10911091
if (take)
1092-
T->vw_initializeWithTake(box.buffer, value);
1092+
T->vw_initializeWithTake(box.second, value);
10931093
else
1094-
T->vw_initializeWithCopy(box.buffer, value);
1095-
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);
1094+
T->vw_initializeWithCopy(box.second, value);
1095+
std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second);
10961096

1097-
Data = {box.object, box.buffer, T};
1097+
Data = {box.first, box.second, T};
10981098
}
10991099

11001100
/// MagicMirror ownership-sharing subvalue constructor.

0 commit comments

Comments
 (0)