Skip to content

[interop][SwiftToCxx] fix the circular depedency issue for struct emi… #60666

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
Aug 20, 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
14 changes: 2 additions & 12 deletions lib/PrintAsClang/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ class DeclAndTypePrinter::Implementation

SmallVector<const FunctionType *, 4> openFunctionTypes;

std::string outOfLineDefinitions;

ASTContext &getASTContext() const {
return owningPrinter.M.getASTContext();
}
Expand Down Expand Up @@ -218,7 +216,6 @@ class DeclAndTypePrinter::Implementation
template <bool AllowDelayed = false, typename R>
void printMembers(R &&members) {
bool protocolMembersOptional = false;
assert(outOfLineDefinitions.empty());
for (const Decl *member : members) {
auto VD = dyn_cast<ValueDecl>(member);
if (!VD || !shouldInclude(VD) || isa<TypeDecl>(VD))
Expand Down Expand Up @@ -302,8 +299,6 @@ class DeclAndTypePrinter::Implementation
// FIXME: Print availability.
ClangClassTypePrinter(os).printClassTypeDecl(
CD, [&]() { printMembers(CD->getMembers()); });
os << outOfLineDefinitions;
outOfLineDefinitions.clear();
return;
}

Expand Down Expand Up @@ -356,8 +351,6 @@ class DeclAndTypePrinter::Implementation
owningPrinter.interopContext);
printer.printValueTypeDecl(
SD, /*bodyPrinter=*/[&]() { printMembers(SD->getMembers()); });
os << outOfLineDefinitions;
outOfLineDefinitions.clear();
}

void visitExtensionDecl(ExtensionDecl *ED) {
Expand Down Expand Up @@ -580,8 +573,6 @@ class DeclAndTypePrinter::Implementation
os << " }\n"; // operator cases()'s closing bracket
os << "\n";
});
os << outOfLineDefinitions;
outOfLineDefinitions.clear();
}

void visitEnumDecl(EnumDecl *ED) {
Expand Down Expand Up @@ -767,10 +758,9 @@ class DeclAndTypePrinter::Implementation
/*isDefinition=*/false);
}

llvm::raw_string_ostream defOS(outOfLineDefinitions);
DeclAndTypeClangFunctionPrinter defPrinter(
defOS, owningPrinter.prologueOS, owningPrinter.typeMapping,
owningPrinter.interopContext);
owningPrinter.outOfLineDefinitionsOS, owningPrinter.prologueOS,
owningPrinter.typeMapping, owningPrinter.interopContext);

if (auto *accessor = dyn_cast<AccessorDecl>(AFD)) {

Expand Down
5 changes: 4 additions & 1 deletion lib/PrintAsClang/DeclAndTypePrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class DeclAndTypePrinter {
ModuleDecl &M;
raw_ostream &os;
raw_ostream &prologueOS;
raw_ostream &outOfLineDefinitionsOS;
const DelayedMemberSet &delayedMembers;
PrimitiveTypeMapping &typeMapping;
SwiftToClangInteropContext &interopContext;
Expand All @@ -57,11 +58,13 @@ class DeclAndTypePrinter {

public:
DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS,
raw_ostream &outOfLineDefinitionsOS,
DelayedMemberSet &delayed,
PrimitiveTypeMapping &typeMapping,
SwiftToClangInteropContext &interopContext,
AccessLevel access, OutputLanguageMode outputLang)
: M(mod), os(out), prologueOS(prologueOS), delayedMembers(delayed),
: M(mod), os(out), prologueOS(prologueOS),
outOfLineDefinitionsOS(outOfLineDefinitionsOS), delayedMembers(delayed),
typeMapping(typeMapping), interopContext(interopContext),
minRequiredAccess(access), outputLang(outputLang) {}

Expand Down
47 changes: 30 additions & 17 deletions lib/PrintAsClang/ModuleContentsWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "DeclAndTypePrinter.h"
#include "OutputLanguageMode.h"
#include "PrimitiveTypeMapping.h"
#include "PrintClangValueType.h"
#include "PrintSwiftToClangCoreScaffold.h"

#include "swift/AST/ExistentialLayout.h"
Expand Down Expand Up @@ -126,6 +127,8 @@ class ModuleWriter {
std::vector<const Decl *> declsToWrite;
DelayedMemberSet delayedMembers;
PrimitiveTypeMapping typeMapping;
std::string outOfLineDefinitions;
llvm::raw_string_ostream outOfLineDefinitionsOS;
DeclAndTypePrinter printer;
OutputLanguageMode outputLangMode;

Expand All @@ -135,8 +138,9 @@ class ModuleWriter {
SwiftToClangInteropContext &interopContext, AccessLevel access,
OutputLanguageMode outputLang)
: os(os), imports(imports), M(mod),
printer(M, os, prologueOS, delayedMembers, typeMapping, interopContext,
access, outputLang),
outOfLineDefinitionsOS(outOfLineDefinitions),
printer(M, os, prologueOS, outOfLineDefinitionsOS, delayedMembers,
typeMapping, interopContext, access, outputLang),
outputLangMode(outputLang) {}

PrimitiveTypeMapping &getTypeMapping() { return typeMapping; }
Expand Down Expand Up @@ -238,14 +242,8 @@ class ModuleWriter {
os << "@protocol " << getNameForObjC(PD) << ";\n";
});
}

void forwardDeclare(const EnumDecl *ED) {
// TODO: skip for now; will overhaul the forward decals for c++ in the
// future
if (outputLangMode == swift::OutputLanguageMode::Cxx) {
return;
}

void forwardDeclare(const EnumDecl *ED) {
assert(ED->isObjC() || ED->hasClangNode());

forwardDeclare(ED, [&]{
Expand All @@ -256,6 +254,14 @@ class ModuleWriter {
}

void forwardDeclareType(const TypeDecl *TD) {
if (outputLangMode == OutputLanguageMode::Cxx) {
if (isa<StructDecl>(TD) || isa<EnumDecl>(TD)) {
auto *NTD = cast<NominalTypeDecl>(TD);
forwardDeclare(
NTD, [&]() { ClangValueTypePrinter::forwardDeclType(os, NTD); });
}
return;
}
if (auto CD = dyn_cast<ClassDecl>(TD)) {
if (!forwardDeclare(CD)) {
(void)addImport(CD);
Expand All @@ -274,9 +280,6 @@ class ModuleWriter {
forwardDeclare(ED);
} else if (isa<AbstractTypeParamDecl>(TD)) {
llvm_unreachable("should not see type params here");
} else if (isa<StructDecl>(TD)) {
// FIXME: add support here.
return;
} else {
assert(false && "unknown local type decl");
}
Expand All @@ -290,6 +293,11 @@ class ModuleWriter {
case DeclKind::Protocol:
case DeclKind::Extension:
break;
case DeclKind::Struct:
case DeclKind::Enum:
if (outputLangMode == OutputLanguageMode::Cxx)
break;
LLVM_FALLTHROUGH;
default:
llvm_unreachable("unexpected container kind");
}
Expand Down Expand Up @@ -346,11 +354,12 @@ class ModuleWriter {
}

// Protocols should be delayed wholesale unless we might have a cycle.
auto *proto = cast<ProtocolDecl>(container);
if (!hasBeenRequested(proto) || !hasBeenRequested(TD)) {
if (!require(TD))
hadAnyDelayedMembers = true;
return;
if (auto *proto = dyn_cast<ProtocolDecl>(container)) {
if (!hasBeenRequested(proto) || !hasBeenRequested(TD)) {
if (!require(TD))
hadAnyDelayedMembers = true;
return;
}
}

// Otherwise, we have a cyclic dependency. Give up and continue with
Expand Down Expand Up @@ -426,6 +435,8 @@ class ModuleWriter {
bool writeStruct(const StructDecl *SD) {
if (addImport(SD))
return true;
if (outputLangMode == OutputLanguageMode::Cxx)
(void)forwardDeclareMemberTypes(SD->getMembers(), SD);
printer.print(SD);
return true;
}
Expand Down Expand Up @@ -646,6 +657,8 @@ class ModuleWriter {
}
printer.printAdHocCategory(make_range(groupBegin, delayedMembers.end()));
}
// Print any out of line definitions.
os << outOfLineDefinitionsOS.str();
}
};
} // end anonymous namespace
Expand Down
7 changes: 7 additions & 0 deletions lib/PrintAsClang/PrintClangValueType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ printCValueTypeStorageStruct(raw_ostream &os, const NominalTypeDecl *typeDecl,
os << "};\n\n";
}

void ClangValueTypePrinter::forwardDeclType(raw_ostream &os,
const NominalTypeDecl *typeDecl) {
os << "class ";
ClangSyntaxPrinter(os).printBaseName(typeDecl);
os << ";\n";
}

void ClangValueTypePrinter::printValueTypeDecl(
const NominalTypeDecl *typeDecl,
llvm::function_ref<void(void)> bodyPrinter) {
Expand Down
2 changes: 2 additions & 0 deletions lib/PrintAsClang/PrintClangValueType.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class ClangValueTypePrinter {
const NominalTypeDecl *typeDecl,
StringRef typeMetadataFuncName);

static void forwardDeclType(raw_ostream &os, const NominalTypeDecl *typeDecl);

private:
/// Prints out the C stub name used to pass/return value directly for the
/// given value type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ public struct UsesEnumsLargeEnum {
public let x: LargeEnum
}

public func inoutLargeEnum(_ s: inout LargeEnum) {
return s = LargeEnum.B
}

// CHECK: inline void inoutLargeEnum(Enums::LargeEnum& s) noexcept {
// CHECK-NEXT: return _impl::$s9UsesEnums14inoutLargeEnumyy0B00dE0OzF(Enums::_impl::_impl_LargeEnum::getOpaquePointer(s));
// CHECK-NEXT: }

// CHECK: inline Enums::LargeEnum UsesEnumsLargeEnum::passThroughStructSeveralI64(const Enums::LargeEnum& y) const {
// CHECK-NEXT: return Enums::_impl::_impl_LargeEnum::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s9UsesEnums0aB9LargeEnumV27passThroughStructSeveralI64y0B00cD0OAGF(result, Enums::_impl::_impl_LargeEnum::getOpaquePointer(y), _getOpaquePointer());
Expand All @@ -31,12 +39,3 @@ public struct UsesEnumsLargeEnum {
// CHECK-NEXT: _impl::$s9UsesEnums0aB9LargeEnumV1x0B00cD0Ovg(result, _getOpaquePointer());
// CHECK-NEXT: });
// CHECK-NEXT: }


public func inoutLargeEnum(_ s: inout LargeEnum) {
return s = LargeEnum.B
}

// CHECK: inline void inoutLargeEnum(Enums::LargeEnum& s) noexcept {
// CHECK-NEXT: return _impl::$s9UsesEnums14inoutLargeEnumyy0B00dE0OzF(Enums::_impl::_impl_LargeEnum::getOpaquePointer(s));
// CHECK-NEXT: }
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,6 @@ public struct UsesStructsStruct {
// CHECK: inline Structs::StructSeveralI64 passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const;
// CHECK-NEXT: inline Structs::StructSeveralI64 getX() const;

// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const {
// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV011passThroughC10SeveralI64y0B00cfG0VAGF(result, Structs::_impl::_impl_StructSeveralI64::getOpaquePointer(y), _getOpaquePointer());
// CHECK-NEXT: });
// CHECK-NEXT: }

// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::getX() const {
// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV1x0B00C10SeveralI64Vvg(result, _getOpaquePointer());
// CHECK-NEXT: });
// CHECK-NEXT: }


public func passThroughStructSeveralI64(_ x: StructSeveralI64) -> StructSeveralI64 {
return Structs.passThroughStructSeveralI64(i: 0, x, j: 2)
Expand Down Expand Up @@ -65,3 +53,15 @@ public func passThroughStructSmallDirect(_ x: SmallStructDirectPassing) -> Small
// CHECK-NEXT: _impl::swift_interop_returnDirect_Structs_SmallStructDirectPassing(result, _impl::$s11UsesStructs28passThroughStructSmallDirecty0B00feG7PassingVAEF(_impl::swift_interop_passDirect_Structs_SmallStructDirectPassing(Structs::_impl::_impl_SmallStructDirectPassing::getOpaquePointer(x))));
// CHECK-NEXT: });
// CHECK-NEXT: }

// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::passThroughStructSeveralI64(const Structs::StructSeveralI64& y) const {
// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV011passThroughC10SeveralI64y0B00cfG0VAGF(result, Structs::_impl::_impl_StructSeveralI64::getOpaquePointer(y), _getOpaquePointer());
// CHECK-NEXT: });
// CHECK-NEXT: }

// CHECK: inline Structs::StructSeveralI64 UsesStructsStruct::getX() const {
// CHECK-NEXT: return Structs::_impl::_impl_StructSeveralI64::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s11UsesStructs0aB6StructV1x0B00C10SeveralI64Vvg(result, _getOpaquePointer());
// CHECK-NEXT: });
// CHECK-NEXT: }
51 changes: 26 additions & 25 deletions test/Interop/SwiftToCxx/initializers/init-in-cxx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,6 @@ public struct FirstSmallStruct {
// CHECK-NEXT: static inline FirstSmallStruct init(swift::Int x);
// CHECK-NEXT: private:

// CHECK: inline uint32_t FirstSmallStruct::getX() const {
// CHECK-NEXT: return _impl::$s4Init16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Init_FirstSmallStruct(_getOpaquePointer()));
// CHECK-NEXT: }
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init() {
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVACycfC());
// CHECK-NEXT: });
// CHECK-NEXT: }
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init(swift::Int x) {
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVyACSicfC(x));
// CHECK-NEXT: });
// CHECK-NEXT: }

public struct LargeStruct {
public let x1, x2, x3, x4, x5, x6: Int

Expand Down Expand Up @@ -80,17 +66,6 @@ public struct LargeStruct {
// CHECK-NEXT: static inline LargeStruct init(swift::Int x, const FirstSmallStruct& y);
// CHECK-NEXT: private:

// CHECK: inline LargeStruct LargeStruct::init() {
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s4Init11LargeStructVACycfC(result);
// CHECK-NEXT: });
// CHECK-NEXT: }
// CHECK-NEXT: inline LargeStruct LargeStruct::init(swift::Int x, const FirstSmallStruct& y) {
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(result, x, _impl::swift_interop_passDirect_Init_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(y)));
// CHECK-NEXT: });
// CHECK-NEXT: }

private class RefCountedClass {
let x: Int

Expand Down Expand Up @@ -118,6 +93,32 @@ public struct StructWithRefCountStoredProp {
// CHECK: static inline StructWithRefCountStoredProp init();
// CHECK-NEXT: static inline StructWithRefCountStoredProp init(swift::Int x);


// CHECK: inline uint32_t FirstSmallStruct::getX() const {
// CHECK-NEXT: return _impl::$s4Init16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Init_FirstSmallStruct(_getOpaquePointer()));
// CHECK-NEXT: }
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init() {
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVACycfC());
// CHECK-NEXT: });
// CHECK-NEXT: }
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init(swift::Int x) {
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVyACSicfC(x));
// CHECK-NEXT: });
// CHECK-NEXT: }

// CHECK: inline LargeStruct LargeStruct::init() {
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s4Init11LargeStructVACycfC(result);
// CHECK-NEXT: });
// CHECK-NEXT: }
// CHECK-NEXT: inline LargeStruct LargeStruct::init(swift::Int x, const FirstSmallStruct& y) {
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
// CHECK-NEXT: _impl::$s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(result, x, _impl::swift_interop_passDirect_Init_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(y)));
// CHECK-NEXT: });
// CHECK-NEXT: }

// CHECK: inline StructWithRefCountStoredProp StructWithRefCountStoredProp::init() {
// CHECK-NEXT: return _impl::_impl_StructWithRefCountStoredProp::returnNewValue([&](char * _Nonnull result) {
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_StructWithRefCountStoredProp(result, _impl::$s4Init28StructWithRefCountStoredPropVACycfC());
Expand Down
Loading