Skip to content

Commit 266a622

Browse files
authored
Merge pull request swiftlang#76011 from swiftlang/gaborh/emit-more-metadata
[cxx-interop] Emit type metadata for foreign types more often
2 parents 009ff8a + cdbe999 commit 266a622

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

lib/IRGen/IRGenSIL.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "GenKeyPath.h"
1919
#include "swift/AST/ASTContext.h"
2020
#include "swift/AST/ASTMangler.h"
21+
#include "swift/AST/Decl.h"
2122
#include "swift/AST/DiagnosticsIRGen.h"
2223
#include "swift/AST/ExtInfo.h"
2324
#include "swift/AST/GenericEnvironment.h"
@@ -26,6 +27,9 @@
2627
#include "swift/AST/Pattern.h"
2728
#include "swift/AST/SemanticAttrs.h"
2829
#include "swift/AST/SubstitutionMap.h"
30+
#include "swift/AST/Type.h"
31+
#include "swift/AST/TypeExpansionContext.h"
32+
#include "swift/AST/TypeVisitor.h"
2933
#include "swift/AST/Types.h"
3034
#include "swift/Basic/Assertions.h"
3135
#include "swift/Basic/ExternalUnion.h"
@@ -2485,6 +2489,53 @@ static void emitDynamicSelfMetadata(IRGenSILFunction &IGF) {
24852489
IGF.setDynamicSelfMetadata(selfTy, isExact, value, selfKind);
24862490
}
24872491

2492+
/// C++ interop might refer to the type metadata in some scenarios.
2493+
/// This function covers those cases and makes sure metadata is emitted
2494+
/// for the foreign types.
2495+
static void noteUseOfMetadataByCXXInterop(IRGenerator &IRGen,
2496+
const SILFunction *f,
2497+
const TypeExpansionContext &context) {
2498+
auto type = f->getLoweredFunctionType();
2499+
2500+
// Notes the use of foreign types in generic arguments for C++ interop.
2501+
auto processType = [&](CanType type) {
2502+
struct Walker : TypeWalker {
2503+
Walker(IRGenerator &IRGen) : IRGen(IRGen) {}
2504+
2505+
Action walkToTypePre(Type ty) override {
2506+
if (auto *BGT = ty->getAs<BoundGenericType>())
2507+
genericDepth++;
2508+
else if (auto *nominal = ty->getAs<NominalType>())
2509+
noteUseOfTypeMetadata(nominal->getDecl());
2510+
return Action::Continue;
2511+
}
2512+
2513+
Action walkToTypePost(Type ty) override {
2514+
if (auto *BGT = ty->getAs<BoundGenericType>())
2515+
genericDepth--;
2516+
2517+
return Action::Continue;
2518+
}
2519+
2520+
void noteUseOfTypeMetadata(NominalTypeDecl *type) {
2521+
if (genericDepth == 0)
2522+
return;
2523+
if (!IRGen.hasLazyMetadata(type) || !type->hasClangNode())
2524+
return;
2525+
IRGen.noteUseOfTypeMetadata(type);
2526+
}
2527+
IRGenerator &IRGen;
2528+
int genericDepth = 0;
2529+
} walker{IRGen};
2530+
type.walk(walker);
2531+
};
2532+
2533+
for (const auto &param : type->getParameters())
2534+
processType(param.getArgumentType(IRGen.SIL, type, context));
2535+
for (const auto &result : type->getResultsWithError())
2536+
processType(result.getReturnValueType(IRGen.SIL, type, context));
2537+
}
2538+
24882539
/// Emit the definition for the given SIL constant.
24892540
void IRGenModule::emitSILFunction(SILFunction *f) {
24902541
if (f->isExternalDeclaration())
@@ -2496,6 +2547,12 @@ void IRGenModule::emitSILFunction(SILFunction *f) {
24962547
f->isAvailableExternally())
24972548
return;
24982549

2550+
// Type metadata for foreign references is not yet supported on Windows. Bug #76168.
2551+
if (Context.LangOpts.EnableCXXInterop &&
2552+
f->getLinkage() == SILLinkage::Public &&
2553+
!Context.LangOpts.Target.isOSWindows())
2554+
noteUseOfMetadataByCXXInterop(IRGen, f, TypeExpansionContext(*f));
2555+
24992556
PrettyStackTraceSILFunction stackTrace("emitting IR", f);
25002557
IRGenSILFunction(*this, f).emitSILFunction();
25012558
}

test/Interop/CxxToSwiftToCxx/link-cxx-type-metadata-accessor.swift

+17
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ struct CxxStruct {
1717
int x;
1818
};
1919

20+
struct CxxStruct2 {
21+
inline CxxStruct2(int x) : x(x) {}
22+
inline CxxStruct2(const CxxStruct &other) : x(other.x) {}
23+
inline ~CxxStruct2() {}
24+
25+
int x;
26+
};
27+
2028
//--- module.modulemap
2129
module CxxTest {
2230
header "header.h"
@@ -30,6 +38,12 @@ public func retCxxStruct() -> CxxStruct {
3038
return CxxStruct(2)
3139
}
3240

41+
#if !os(Windows)
42+
public func retCxxStruct2() -> CxxStruct2? {
43+
return CxxStruct2(2)
44+
}
45+
#endif
46+
3347
//--- use-swift-cxx-types.cpp
3448

3549
#include "header.h"
@@ -38,5 +52,8 @@ public func retCxxStruct() -> CxxStruct {
3852

3953
int main() {
4054
auto x = UseCxx::retCxxStruct();
55+
#ifndef _WIN32
56+
auto y = UseCxx::retCxxStruct2();
57+
#endif
4158
return 0;
4259
}

0 commit comments

Comments
 (0)