Skip to content

Commit 85f48ae

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 35fbafd + 7701ddc commit 85f48ae

20 files changed

+528
-130
lines changed

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -94,47 +94,8 @@ void ClangClassTypePrinter::printClassTypeDecl(
9494
os << "};\n";
9595
});
9696

97-
// FIXME: avoid popping out of the module's namespace here.
98-
os << "} // end namespace \n\n";
99-
os << "namespace swift {\n";
100-
101-
os << "#pragma clang diagnostic push\n";
102-
os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
103-
os << "template<>\n";
104-
os << "static inline const constexpr bool isUsableInGenericContext<";
105-
printer.printBaseName(typeDecl->getModuleContext());
106-
os << "::";
107-
printer.printBaseName(typeDecl);
108-
os << "> = true;\n";
109-
os << "#pragma clang diagnostic pop\n";
110-
111-
os << "template<>\n";
112-
os << "inline void * _Nonnull getTypeMetadata<";
113-
printer.printBaseName(typeDecl->getModuleContext());
114-
os << "::";
115-
printer.printBaseName(typeDecl);
116-
os << ">() {\n";
117-
os << " return ";
118-
printer.printBaseName(typeDecl->getModuleContext());
119-
os << "::" << cxx_synthesis::getCxxImplNamespaceName()
120-
<< "::" << typeMetadataFuncName << "(0)._0;\n";
121-
os << "}\n";
122-
os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << "{\n";
123-
os << "template<>\n";
124-
os << "struct implClassFor<";
125-
printer.printBaseName(typeDecl->getModuleContext());
126-
os << "::";
127-
printer.printBaseName(typeDecl);
128-
os << "> { using type = ";
129-
printer.printBaseName(typeDecl->getModuleContext());
130-
os << "::" << cxx_synthesis::getCxxImplNamespaceName() << "::";
131-
printCxxImplClassName(os, typeDecl);
132-
os << "; };\n";
133-
os << "} // namespace\n";
134-
os << "} // namespace swift\n";
135-
os << "\nnamespace ";
136-
printer.printBaseName(typeDecl->getModuleContext());
137-
os << " {\n";
97+
ClangValueTypePrinter::printTypeGenericTraits(os, typeDecl,
98+
typeMetadataFuncName);
13899
}
139100

140101
void ClangClassTypePrinter::printClassTypeReturnScaffold(

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -451,13 +451,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
451451
if (type->getAs<ArchetypeType>() && type->getAs<ArchetypeType>()
452452
->getInterfaceType()
453453
->is<GenericTypeParamType>()) {
454-
// FIXME: NEED to handle boxed resilient type.
455-
// os << "swift::" << cxx_synthesis::getCxxImplNamespaceName() <<
456-
// "::getOpaquePointer(";
457-
os << "reinterpret_cast<";
458-
if (!isInOut)
459-
os << "const ";
460-
os << "void *>(&";
454+
os << "swift::" << cxx_synthesis::getCxxImplNamespaceName()
455+
<< "::getOpaquePointer(";
461456
namePrinter();
462457
os << ')';
463458
return;
@@ -576,10 +571,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
576571
if (!isKnownCxxType(resultTy, typeMapping) &&
577572
!hasKnownOptionalNullableCxxMapping(resultTy)) {
578573
if (isGenericType(resultTy)) {
579-
// FIXME: Support returning value types.
580574
std::string returnAddress;
581575
llvm::raw_string_ostream ros(returnAddress);
582576
ros << "reinterpret_cast<void *>(&returnValue)";
577+
StringRef resultTyName = "T"; // FIXME
583578

584579
os << " if constexpr (std::is_base_of<::swift::"
585580
<< cxx_synthesis::getCxxImplNamespaceName()
@@ -589,6 +584,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
589584
os << ";\n";
590585
os << " return ::swift::" << cxx_synthesis::getCxxImplNamespaceName()
591586
<< "::implClassFor<T>::type::makeRetained(returnValue);\n";
587+
os << " } else if constexpr (::swift::"
588+
<< cxx_synthesis::getCxxImplNamespaceName() << "::isValueType<"
589+
<< resultTyName << ">) {\n";
590+
os << " return ::swift::" << cxx_synthesis::getCxxImplNamespaceName()
591+
<< "::implClassFor<" << resultTyName
592+
<< ">::type::returnNewValue([&](void * _Nonnull returnValue) {\n";
593+
printCallToCFunc(/*additionalParam=*/StringRef("returnValue"));
594+
os << ";\n });\n";
592595
os << " } else {\n";
593596
os << " T returnValue;\n";
594597
printCallToCFunc(/*additionalParam=*/StringRef(ros.str()));

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ void ClangValueTypePrinter::printValueTypeDecl(
152152
if (isOpaqueLayout) {
153153
os << " _storage = ";
154154
printer.printSwiftImplQualifier();
155-
os << cxx_synthesis::getCxxOpaqueStorageClassName() << "(vwTable);\n";
155+
os << cxx_synthesis::getCxxOpaqueStorageClassName()
156+
<< "(vwTable->size, vwTable->getAlignment());\n";
156157
}
157158
os << " vwTable->initializeWithCopy(_getOpaquePointer(), const_cast<char "
158159
"*>(other._getOpaquePointer()), metadata._0);\n";
@@ -172,10 +173,12 @@ void ClangValueTypePrinter::printValueTypeDecl(
172173
// Print out private default constructor.
173174
os << " inline ";
174175
printer.printBaseName(typeDecl);
176+
// FIXME: make noexcept.
175177
if (isOpaqueLayout) {
176178
os << "(";
177179
printer.printSwiftImplQualifier();
178-
os << "ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable) {}\n";
180+
os << "ValueWitnessTable * _Nonnull vwTable) : _storage(vwTable->size, "
181+
"vwTable->getAlignment()) {}\n";
179182
} else {
180183
os << "() {}\n";
181184
}
@@ -281,6 +284,8 @@ void ClangValueTypePrinter::printValueTypeDecl(
281284

282285
if (!isOpaqueLayout)
283286
printCValueTypeStorageStruct(cPrologueOS, typeDecl, *typeSizeAlign);
287+
288+
printTypeGenericTraits(os, typeDecl, typeMetadataFuncName);
284289
}
285290

286291
/// Print the name of the C stub struct for passing/returning a value type
@@ -456,3 +461,68 @@ void ClangValueTypePrinter::printValueTypeDirectReturnScaffold(
456461
os << ");\n";
457462
os << " });\n";
458463
}
464+
465+
void ClangValueTypePrinter::printTypeGenericTraits(
466+
raw_ostream &os, const NominalTypeDecl *typeDecl,
467+
StringRef typeMetadataFuncName) {
468+
ClangSyntaxPrinter printer(os);
469+
// FIXME: avoid popping out of the module's namespace here.
470+
os << "} // end namespace \n\n";
471+
os << "namespace swift {\n";
472+
473+
os << "#pragma clang diagnostic push\n";
474+
os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
475+
os << "template<>\n";
476+
os << "static inline const constexpr bool isUsableInGenericContext<";
477+
printer.printBaseName(typeDecl->getModuleContext());
478+
os << "::";
479+
printer.printBaseName(typeDecl);
480+
os << "> = true;\n";
481+
os << "template<>\n";
482+
os << "inline void * _Nonnull getTypeMetadata<";
483+
printer.printBaseName(typeDecl->getModuleContext());
484+
os << "::";
485+
printer.printBaseName(typeDecl);
486+
os << ">() {\n";
487+
os << " return ";
488+
printer.printBaseName(typeDecl->getModuleContext());
489+
os << "::" << cxx_synthesis::getCxxImplNamespaceName()
490+
<< "::" << typeMetadataFuncName << "(0)._0;\n";
491+
os << "}\n";
492+
493+
os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << "{\n";
494+
495+
if (!isa<ClassDecl>(typeDecl)) {
496+
os << "template<>\n";
497+
os << "static inline const constexpr bool isValueType<";
498+
printer.printBaseName(typeDecl->getModuleContext());
499+
os << "::";
500+
printer.printBaseName(typeDecl);
501+
os << "> = true;\n";
502+
if (typeDecl->isResilient()) {
503+
os << "template<>\n";
504+
os << "static inline const constexpr bool isOpaqueLayout<";
505+
printer.printBaseName(typeDecl->getModuleContext());
506+
os << "::";
507+
printer.printBaseName(typeDecl);
508+
os << "> = true;\n";
509+
}
510+
}
511+
512+
os << "template<>\n";
513+
os << "struct implClassFor<";
514+
printer.printBaseName(typeDecl->getModuleContext());
515+
os << "::";
516+
printer.printBaseName(typeDecl);
517+
os << "> { using type = ";
518+
printer.printBaseName(typeDecl->getModuleContext());
519+
os << "::" << cxx_synthesis::getCxxImplNamespaceName() << "::";
520+
printCxxImplClassName(os, typeDecl);
521+
os << "; };\n";
522+
os << "} // namespace\n";
523+
os << "#pragma clang diagnostic pop\n";
524+
os << "} // namespace swift\n";
525+
os << "\nnamespace ";
526+
printer.printBaseName(typeDecl->getModuleContext());
527+
os << " {\n";
528+
}

lib/PrintAsClang/PrintClangValueType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class ClangValueTypePrinter {
9494
StringRef metadataVarName = "metadata",
9595
StringRef vwTableVarName = "vwTable");
9696

97+
static void printTypeGenericTraits(raw_ostream &os,
98+
const NominalTypeDecl *typeDecl,
99+
StringRef typeMetadataFuncName);
100+
97101
private:
98102
/// Prints out the C stub name used to pass/return value directly for the
99103
/// given value type.

lib/PrintAsClang/PrintSwiftToClangCoreScaffold.cpp

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ static void printValueWitnessTable(raw_ostream &os) {
111111
#define VOID_TYPE "void"
112112
#include "swift/ABI/ValueWitness.def"
113113

114+
membersOS << "\n constexpr size_t getAlignment() const { return (flags & "
115+
<< TargetValueWitnessFlags<uint64_t>::AlignmentMask << ") + 1; }\n";
114116
os << "\nstruct ValueWitnessTable {\n" << membersOS.str() << "};\n\n";
115117
membersOS.str().clear();
116118

@@ -154,43 +156,7 @@ static void printTypeMetadataResponseType(SwiftToClangInteropContext &ctx,
154156
funcSig.parameterTypes[0]);
155157
}
156158

157-
static void printSwiftResilientStorageClass(raw_ostream &os) {
158-
auto name = cxx_synthesis::getCxxOpaqueStorageClassName();
159-
static_assert(TargetValueWitnessFlags<uint64_t>::AlignmentMask ==
160-
TargetValueWitnessFlags<uint32_t>::AlignmentMask,
161-
"alignment mask doesn't match");
162-
os << "/// Container for an opaque Swift value, like resilient struct.\n";
163-
os << "class " << name << " {\n";
164-
os << "public:\n";
165-
os << " inline " << name << "() noexcept : storage(nullptr) { }\n";
166-
os << " inline " << name
167-
<< "(ValueWitnessTable * _Nonnull vwTable) noexcept : storage("
168-
"reinterpret_cast<char *>(opaqueAlloc(vwTable->size, (vwTable->flags &"
169-
<< TargetValueWitnessFlags<uint64_t>::AlignmentMask << ") + 1))) { }\n";
170-
os << " inline " << name << "(" << name
171-
<< "&& other) noexcept : storage(other.storage) { other.storage = "
172-
"nullptr; }\n";
173-
os << " inline " << name << "(const " << name << "&) noexcept = delete;\n";
174-
os << " inline ~" << name
175-
<< "() noexcept { if (storage) { opaqueFree(static_cast<char "
176-
"* _Nonnull>(storage)); } }\n";
177-
os << " void operator =(" << name
178-
<< "&& other) noexcept { auto temp = storage; storage = other.storage; "
179-
"other.storage = temp; }\n";
180-
os << " void operator =(const " << name << "&) noexcept = delete;\n";
181-
os << " inline char * _Nonnull getOpaquePointer() noexcept { return "
182-
"static_cast<char "
183-
"* _Nonnull>(storage); }\n";
184-
os << " inline const char * _Nonnull getOpaquePointer() const noexcept { "
185-
"return "
186-
"static_cast<char * _Nonnull>(storage); }\n";
187-
os << "private:\n";
188-
os << " char * _Nullable storage;\n";
189-
os << "};\n";
190-
}
191-
192159
void printCxxNaiveException(raw_ostream &os) {
193-
os << "\n";
194160
os << "/// Naive exception class that should be thrown\n";
195161
os << "class NaiveException {\n";
196162
os << "public:\n";
@@ -273,7 +239,6 @@ void swift::printSwiftToClangCoreScaffold(SwiftToClangInteropContext &ctx,
273239
/*isCForwardDefinition=*/true);
274240
});
275241
os << "\n";
276-
printSwiftResilientStorageClass(os);
277242
printCxxNaiveException(os);
278243
});
279244
os << "\n";

stdlib/public/SwiftShims/_SwiftCxxInteroperability.h

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,42 @@ inline void opaqueFree(void *_Nonnull p) noexcept {
5353
#endif
5454
}
5555

56+
/// Base class for a container for an opaque Swift value, like resilient struct.
57+
class OpaqueStorage {
58+
public:
59+
inline OpaqueStorage() noexcept : storage(nullptr) {}
60+
inline OpaqueStorage(size_t size, size_t alignment) noexcept
61+
: storage(reinterpret_cast<char *>(opaqueAlloc(size, alignment))) {}
62+
inline OpaqueStorage(OpaqueStorage &&other) noexcept
63+
: storage(other.storage) {
64+
other.storage = nullptr;
65+
}
66+
inline OpaqueStorage(const OpaqueStorage &) noexcept = delete;
67+
68+
inline ~OpaqueStorage() noexcept {
69+
if (storage) {
70+
opaqueFree(static_cast<char *_Nonnull>(storage));
71+
}
72+
}
73+
74+
void operator=(OpaqueStorage &&other) noexcept {
75+
auto temp = storage;
76+
storage = other.storage;
77+
other.storage = temp;
78+
}
79+
void operator=(const OpaqueStorage &) noexcept = delete;
80+
81+
inline char *_Nonnull getOpaquePointer() noexcept {
82+
return static_cast<char *_Nonnull>(storage);
83+
}
84+
inline const char *_Nonnull getOpaquePointer() const noexcept {
85+
return static_cast<char *_Nonnull>(storage);
86+
}
87+
88+
private:
89+
char *_Nullable storage;
90+
};
91+
5692
/// Base class for a Swift reference counted class value.
5793
class RefCountedClass {
5894
public:
@@ -104,8 +140,6 @@ using UInt = size_t;
104140
template <class T>
105141
static inline const constexpr bool isUsableInGenericContext = false;
106142

107-
#pragma clang diagnostic pop
108-
109143
/// Returns the type metadat for the given Swift type T.
110144
template <class T> inline void *_Nonnull getTypeMetadata();
111145

@@ -117,8 +151,31 @@ template <class T> struct implClassFor {
117151
// using type = ...;
118152
};
119153

154+
/// True if the given type is a Swift value type.
155+
template <class T> static inline const constexpr bool isValueType = false;
156+
157+
/// True if the given type is a Swift value type with opaque layout that can be
158+
/// boxed.
159+
template <class T> static inline const constexpr bool isOpaqueLayout = false;
160+
161+
/// Returns the opaque pointer to the given value.
162+
template <class T>
163+
inline const void *_Nonnull getOpaquePointer(const T &value) {
164+
if constexpr (isOpaqueLayout<T>)
165+
return reinterpret_cast<const OpaqueStorage &>(value).getOpaquePointer();
166+
return reinterpret_cast<const void *>(&value);
167+
}
168+
169+
template <class T> inline void *_Nonnull getOpaquePointer(T &value) {
170+
if constexpr (isOpaqueLayout<T>)
171+
return reinterpret_cast<OpaqueStorage &>(value).getOpaquePointer();
172+
return reinterpret_cast<void *>(&value);
173+
}
174+
120175
} // namespace _impl
121176

177+
#pragma clang diagnostic pop
178+
122179
} // namespace swift
123180
#endif
124181

stdlib/public/core/SmallString.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,13 +353,22 @@ extension _SmallString {
353353
//
354354
@_effects(readonly) // @opaque
355355
@usableFromInline // testable
356-
internal init(taggedCocoa cocoa: AnyObject) {
356+
internal init?(taggedCocoa cocoa: AnyObject) {
357357
self.init()
358+
var success = true
358359
self.withMutableCapacity {
359-
let len = _bridgeTagged(cocoa, intoUTF8: $0)
360-
_internalInvariant(len != nil && len! <= _SmallString.capacity,
361-
"Internal invariant violated: large tagged NSStrings")
362-
return len._unsafelyUnwrappedUnchecked
360+
/*
361+
For regular NSTaggedPointerStrings we will always succeed here, but
362+
tagged NSLocalizedStrings may not fit in a SmallString
363+
*/
364+
if let len = _bridgeTagged(cocoa, intoUTF8: $0) {
365+
return len
366+
}
367+
success = false
368+
return 0
369+
}
370+
if !success {
371+
return nil
363372
}
364373
self._invariantCheck()
365374
}

0 commit comments

Comments
 (0)