Skip to content

[interop][SwiftToCxx] expose generic type traits for C++ types in gen… #61072

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
Sep 13, 2022
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
15 changes: 10 additions & 5 deletions lib/PrintAsClang/ModuleContentsWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class ModuleWriter {
ModuleDecl &M;

llvm::DenseMap<const TypeDecl *, std::pair<EmissionState, bool>> seenTypes;
llvm::DenseSet<const NominalTypeDecl *> seenClangTypes;
std::vector<const Decl *> declsToWrite;
DelayedMemberSet delayedMembers;
PrimitiveTypeMapping typeMapping;
Expand Down Expand Up @@ -267,13 +268,22 @@ class ModuleWriter {
});
}

void emitReferencedClangTypeMetadata(const NominalTypeDecl *typeDecl) {
auto it = seenClangTypes.insert(typeDecl);
if (it.second)
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M);
}

void forwardDeclareType(const TypeDecl *TD) {
if (outputLangMode == OutputLanguageMode::Cxx) {
if (isa<StructDecl>(TD) || isa<EnumDecl>(TD)) {
auto *NTD = cast<NominalTypeDecl>(TD);
if (!addImport(NTD)) {
forwardDeclare(
NTD, [&]() { ClangValueTypePrinter::forwardDeclType(os, NTD); });
} else {
if (isa<StructDecl>(TD) && NTD->hasClangNode())
emitReferencedClangTypeMetadata(NTD);
}
}
return;
Expand Down Expand Up @@ -703,11 +713,6 @@ class ModuleWriter {

// Print any out of line definitions.
os << outOfLineDefinitionsOS.str();

// Print any additional metadata for referenced C++ types.
for (const auto *typeDecl :
printer.getInteropContext().getEmittedClangTypeDecls())
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M);
}
};
} // end anonymous namespace
Expand Down
1 change: 0 additions & 1 deletion lib/PrintAsClang/PrintClangFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ class CFunctionSignatureTypePrinter
handler.printTypeName(os);
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
os << '&';
interopContext.recordEmittedClangTypeDecl(decl);
return ClangRepresentation::representable;
}

Expand Down
6 changes: 0 additions & 6 deletions lib/PrintAsClang/SwiftToClangInteropContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ void SwiftToClangInteropContext::runIfStubForDeclNotEmitted(
function();
}

void SwiftToClangInteropContext::recordEmittedClangTypeDecl(
const NominalTypeDecl *typeDecl) {
assert(typeDecl->hasClangNode());
referencedClangTypeDecls.insert(typeDecl);
}

void SwiftToClangInteropContext::recordExtensions(
const NominalTypeDecl *typeDecl, const ExtensionDecl *ext) {
auto it = extensions.insert(
Expand Down
11 changes: 0 additions & 11 deletions lib/PrintAsClang/SwiftToClangInteropContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringSet.h"
#include <memory>

Expand Down Expand Up @@ -46,15 +45,6 @@ class SwiftToClangInteropContext {
void runIfStubForDeclNotEmitted(llvm::StringRef stubName,
llvm::function_ref<void(void)> function);

/// Records that the given nominal type decl that has a clang declaration was
/// emitted in the generated header.
void recordEmittedClangTypeDecl(const NominalTypeDecl *typeDecl);

inline const llvm::SetVector<const NominalTypeDecl *> &
getEmittedClangTypeDecls() const {
return referencedClangTypeDecls;
}

void recordExtensions(const NominalTypeDecl *typeDecl,
const ExtensionDecl *ext);

Expand All @@ -66,7 +56,6 @@ class SwiftToClangInteropContext {
const IRGenOptions &irGenOpts;
std::unique_ptr<IRABIDetailsProvider> irABIDetails;
llvm::StringSet<> emittedStubs;
llvm::SetVector<const NominalTypeDecl *> referencedClangTypeDecls;
llvm::DenseMap<const NominalTypeDecl *, std::vector<const ExtensionDecl *>>
extensions;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -parse-as-library %platform-module-dir/Swift.swiftmodule/%module-target-triple.swiftinterface -enable-library-evolution -disable-objc-attr-requires-foundation-module -typecheck -module-name Swift -parse-stdlib -enable-experimental-cxx-interop -emit-clang-header-path %t/Swift.h -experimental-skip-all-function-bodies

// RUN: %target-swift-frontend -typecheck %t/use-cxx-types.swift -typecheck -module-name UseCxx -emit-clang-header-path %t/UseCxx.h -I %t -enable-experimental-cxx-interop -clang-header-expose-public-decls

// RUN: %target-interop-build-clangxx -std=c++20 -c %t/use-swift-cxx-types.cpp -I %t -o %t/swift-cxx-execution.o -g
Expand Down Expand Up @@ -88,9 +90,14 @@ public func retPassThroughGeneric<T>(_ x: T) -> T {
return x
}

public func retArrayNonTrivial(_ x: CInt) -> [NonTrivialTemplate<Trivial>] {
return [NonTrivialTemplate<Trivial>(Trivial(x, -x))]
}

//--- use-swift-cxx-types.cpp

#include "header.h"
#include "Swift.h"
#include "UseCxx.h"
#include <assert.h>

Expand Down Expand Up @@ -134,7 +141,6 @@ int main() {
}
puts("secondon non trivial");
}
puts("EndOfTest");
// CHECK-NEXT: create NonTrivialTemplate
// CHECK-NEXT: move NonTrivialTemplate
// CHECK-NEXT: ~NonTrivialTemplate
Expand All @@ -158,6 +164,19 @@ int main() {
// CHECK-NEXT: ~NonTrivialTemplate
// CHECK-NEXT: secondon non trivial
// CHECK-NEXT: ~NonTrivialTemplate
{
auto arr = UseCxx::retArrayNonTrivial(1234);
auto val = arr[0];
assert(val.x.x == 1234);
assert(val.x.y == -1234);
}
// CHECK-NEXT: create NonTrivialTemplate
// CHECK-NEXT: copy NonTrivialTemplate
// CHECK-NEXT: move NonTrivialTemplate
// CHECK-NEXT: ~NonTrivialTemplate
// CHECK-NEXT: ~NonTrivialTemplate
// CHECK-NEXT: ~NonTrivialTemplate
puts("EndOfTest");
// CHECK-NEXT: EndOfTest
return 0;
}
91 changes: 60 additions & 31 deletions test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,36 @@ public func takeTrivialInout(_ x: inout Trivial) {
// CHECK: SWIFT_EXTERN void $s8UseCxxTy13retNonTrivialSo2nsO02__b18TemplateInstN2ns18efH4IiEEVyF(SWIFT_INDIRECT_RESULT void * _Nonnull) SWIFT_NOEXCEPT SWIFT_CALL; // retNonTrivial()
// CHECK: SWIFT_EXTERN struct swift_interop_returnStub_UseCxxTy_uint32_t_0_4 $s8UseCxxTy10retTrivialSo0E0VyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // retTrivial()

// CHECK: } // end namespace
// CHECK-EMPTY:
// CHECK-NEXT: namespace swift {
// CHECK-NEXT: namespace _impl {
// CHECK-EMPTY:
// CHECK-NEXT: // Type metadata accessor for __CxxTemplateInstN2ns18NonTrivialTemplateIiEE
// CHECK-NEXT: SWIFT_EXTERN swift::_impl::MetadataResponseTy $sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC4IiEEVMa(swift::_impl::MetadataRequestTy) SWIFT_NOEXCEPT SWIFT_CALL;
// CHECK-EMPTY:
// CHECK-EMPTY:
// CHECK-NEXT: } // namespace _impl
// CHECK-EMPTY:
// CHECK-NEXT: #pragma clang diagnostic push
// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions"
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext<ns::NonTrivialTemplate<int>> = true;
// CHECK-NEXT: template<>
// CHECK-NEXT: struct TypeMetadataTrait<ns::NonTrivialTemplate<int>> {
// CHECK-NEXT: static inline void * _Nonnull getTypeMetadata() {
// CHECK-NEXT: return _impl::$sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC4IiEEVMa(0)._0;
// CHECK-NEXT: }
// CHECK-NEXT: };
// CHECK-NEXT: namespace _impl{
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isSwiftBridgedCxxRecord<ns::NonTrivialTemplate<int>> = true;
// CHECK-NEXT: } // namespace
// CHECK-NEXT: #pragma clang diagnostic pop
// CHECK-NEXT: } // namespace swift
// CHECK-EMPTY:
// CHECK-NEXT: namespace UseCxxTy {

// CHECK: inline ns::NonTrivialTemplate<int> retNonTrivial() noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: alignas(alignof(ns::NonTrivialTemplate<int>)) char storage[sizeof(ns::NonTrivialTemplate<int>)];
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<ns::NonTrivialTemplate<int> *>(storage);
Expand All @@ -101,8 +131,37 @@ public func takeTrivialInout(_ x: inout Trivial) {
// CHECK-NEXT: return result;
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: } // end namespace
// CHECK-EMPTY:
// CHECK-NEXT: namespace swift {
// CHECK-NEXT: namespace _impl {
// CHECK-EMPTY:
// CHECK-NEXT: // Type metadata accessor for __CxxTemplateInstN2ns18NonTrivialTemplateINS_11TrivialinNSEEE
// CHECK-NEXT: SWIFT_EXTERN swift::_impl::MetadataResponseTy $sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC20INS_11TrivialinNSEEEVMa(swift::_impl::MetadataRequestTy) SWIFT_NOEXCEPT SWIFT_CALL;
// CHECK-EMPTY:
// CHECK-EMPTY:
// CHECK-NEXT: } // namespace _impl
// CHECK-EMPTY:
// CHECK-NEXT: #pragma clang diagnostic push
// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions"
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext<ns::NonTrivialTemplate<ns::TrivialinNS>> = true;
// CHECK-NEXT: template<>
// CHECK-NEXT: struct TypeMetadataTrait<ns::NonTrivialTemplate<ns::TrivialinNS>> {
// CHECK-NEXT: static inline void * _Nonnull getTypeMetadata() {
// CHECK-NEXT: return _impl::$sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC20INS_11TrivialinNSEEEVMa(0)._0;
// CHECK-NEXT: }
// CHECK-NEXT: };
// CHECK-NEXT: namespace _impl{
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isSwiftBridgedCxxRecord<ns::NonTrivialTemplate<ns::TrivialinNS>> = true;
// CHECK-NEXT: } // namespace
// CHECK-NEXT: #pragma clang diagnostic pop
// CHECK-NEXT: } // namespace swift
// CHECK-EMPTY:
// CHECK-NEXT: namespace UseCxxTy {
// CHECK-EMPTY:
// CHECK: inline ns::NonTrivialTemplate<ns::TrivialinNS> retNonTrivial2() noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: inline ns::NonTrivialTemplate<ns::TrivialinNS> retNonTrivial2() noexcept SWIFT_WARN_UNUSED_RESULT {
// CHECK-NEXT: alignas(alignof(ns::NonTrivialTemplate<ns::TrivialinNS>)) char storage[sizeof(ns::NonTrivialTemplate<ns::TrivialinNS>)];
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<ns::NonTrivialTemplate<ns::TrivialinNS> *>(storage);
// CHECK-NEXT: _impl::$s8UseCxxTy14retNonTrivial2So2nsO02__b18TemplateInstN2ns18e7TrivialH20INS_11TrivialinNSEEEVyF(storage);
Expand Down Expand Up @@ -140,33 +199,3 @@ public func takeTrivialInout(_ x: inout Trivial) {
// CHECK: inline void takeTrivialInout(Trivial& x) noexcept {
// CHECK-NEXT: return _impl::$s8UseCxxTy16takeTrivialInoutyySo0E0VzF(swift::_impl::getOpaquePointer(x));
// CHECK-NEXT: }

// CHECK: } // end namespace
// CHECK-EMPTY:
// CHECK-NEXT: namespace swift {
// CHECK-NEXT: namespace _impl {
// CHECK-EMPTY:
// CHECK-NEXT: // Type metadata accessor for __CxxTemplateInstN2ns18NonTrivialTemplateIiEE
// CHECK-NEXT: SWIFT_EXTERN swift::_impl::MetadataResponseTy $sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC4IiEEVMa(swift::_impl::MetadataRequestTy) SWIFT_NOEXCEPT SWIFT_CALL;
// CHECK-EMPTY:
// CHECK-EMPTY:
// CHECK-NEXT: } // namespace _impl
// CHECK-EMPTY:
// CHECK-NEXT: #pragma clang diagnostic push
// CHECK-NEXT: #pragma clang diagnostic ignored "-Wc++17-extensions"
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext<ns::NonTrivialTemplate<int>> = true;
// CHECK-NEXT: template<>
// CHECK-NEXT: struct TypeMetadataTrait<ns::NonTrivialTemplate<int>> {
// CHECK-NEXT: static inline void * _Nonnull getTypeMetadata() {
// CHECK-NEXT: return _impl::$sSo2nsO033__CxxTemplateInstN2ns18NonTrivialC4IiEEVMa(0)._0;
// CHECK-NEXT: }
// CHECK-NEXT: };
// CHECK-NEXT: namespace _impl{
// CHECK-NEXT: template<>
// CHECK-NEXT: static inline const constexpr bool isSwiftBridgedCxxRecord<ns::NonTrivialTemplate<int>> = true;
// CHECK-NEXT: } // namespace
// CHECK-NEXT: #pragma clang diagnostic pop
// CHECK-NEXT: } // namespace swift
// CHECK-EMPTY:
// CHECK-NEXT: namespace UseCxxTy {