Skip to content

Commit d06929c

Browse files
committed
[embedded] Add support for some foreign metadata
1 parent 93e494b commit d06929c

File tree

4 files changed

+166
-15
lines changed

4 files changed

+166
-15
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5308,7 +5308,8 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53085308

53095309
return cast<llvm::GlobalValue>(addr);
53105310
}
5311-
5311+
bool hasEmbeddedExistentials =
5312+
Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
53125313
auto entity =
53135314
(isPrespecialized &&
53145315
!irgen::isCanonicalInitializableTypeMetadataStaticallyAddressable(
@@ -5324,7 +5325,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53245325
if (Context.LangOpts.hasFeature(Feature::Embedded)) {
53255326
entity = LinkEntity::forTypeMetadata(concreteType,
53265327
TypeMetadataAddress::AddressPoint);
5327-
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
5328+
if (hasEmbeddedExistentials)
53285329
entity = LinkEntity::forTypeMetadata(concreteType,
53295330
TypeMetadataAddress::FullMetadata);
53305331
}
@@ -5350,7 +5351,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53505351
markGlobalAsUsedBasedOnLinkage(*this, link, var);
53515352

53525353
if (Context.LangOpts.hasFeature(Feature::Embedded) &&
5353-
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
5354+
!hasEmbeddedExistentials) {
53545355
return var;
53555356
}
53565357

@@ -5361,14 +5362,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53615362
if (auto nominal = concreteType->getAnyNominal()) {
53625363
// Keep type metadata around for all types (except @_objcImplementation,
53635364
// since we're using ObjC metadata for that).
5364-
if (!isObjCImpl &&
5365-
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
5365+
if (!isObjCImpl && !hasEmbeddedExistentials)
53665366
addRuntimeResolvableType(nominal);
53675367

53685368
// Don't define the alias for foreign type metadata, prespecialized
53695369
// generic metadata, or @_objcImplementation classes, since they're not ABI.
5370-
if (requiresForeignTypeMetadata(nominal) ||
5371-
(isPrespecialized && !Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) ||
5370+
if ((requiresForeignTypeMetadata(nominal) && !hasEmbeddedExistentials) ||
5371+
(isPrespecialized && !hasEmbeddedExistentials) ||
53725372
isObjCImpl)
53735373
return var;
53745374

@@ -5382,7 +5382,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53825382
}
53835383
}
53845384

5385-
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
5385+
if (hasEmbeddedExistentials) {
53865386
adjustmentIndex = MetadataAdjustmentIndex::EmbeddedWithExistentials;
53875387
}
53885388

lib/IRGen/GenMeta.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7202,46 +7202,61 @@ void irgen::emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl) {
72027202
auto init = builder.beginStruct();
72037203
init.setPacked(true);
72047204

7205+
auto isEmbedded =
7206+
IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
7207+
72057208
if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
72067209
if (classDecl->isForeignReferenceType()) {
7210+
assert(!isEmbedded && "emitting foregin reference type not supported");
72077211
ForeignReferenceTypeMetadataBuilder builder(IGM, classDecl, init);
72087212
builder.layout();
72097213

72107214
IGM.defineTypeMetadata(type, /*isPattern=*/false,
72117215
builder.canBeConstant(),
72127216
init.finishAndCreateFuture());
7213-
builder.createMetadataAccessFunction();
7217+
if (!isEmbedded)
7218+
builder.createMetadataAccessFunction();
72147219
} else {
72157220
assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
7221+
assert(!isEmbedded && "emitting foregin cf class type not supported");
72167222

72177223
ForeignClassMetadataBuilder builder(IGM, classDecl, init);
72187224
builder.layout();
72197225

72207226
IGM.defineTypeMetadata(type, /*isPattern=*/false,
72217227
builder.canBeConstant(),
72227228
init.finishAndCreateFuture());
7223-
builder.createMetadataAccessFunction();
7229+
if (!isEmbedded)
7230+
builder.createMetadataAccessFunction();
72247231
}
72257232
} else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
72267233
assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext()));
72277234

72287235
ForeignStructMetadataBuilder builder(IGM, structDecl, init);
7229-
builder.layout();
7236+
if (isEmbedded)
7237+
builder.embeddedLayout();
7238+
else
7239+
builder.layout();
72307240

72317241
IGM.defineTypeMetadata(type, /*isPattern=*/false,
72327242
builder.canBeConstant(),
72337243
init.finishAndCreateFuture());
7234-
builder.createMetadataAccessFunction();
7244+
if (!isEmbedded)
7245+
builder.createMetadataAccessFunction();
72357246
} else if (auto enumDecl = dyn_cast<EnumDecl>(decl)) {
72367247
assert(enumDecl->hasClangNode());
7237-
7248+
72387249
ForeignEnumMetadataBuilder builder(IGM, enumDecl, init);
7239-
builder.layout();
7250+
if (isEmbedded)
7251+
builder.embeddedLayout();
7252+
else
7253+
builder.layout();
72407254

72417255
IGM.defineTypeMetadata(type, /*isPattern=*/false,
72427256
builder.canBeConstant(),
72437257
init.finishAndCreateFuture());
7244-
builder.createMetadataAccessFunction();
7258+
if (!isEmbedded)
7259+
builder.createMetadataAccessFunction();
72457260
} else {
72467261
llvm_unreachable("foreign metadata for unexpected type?!");
72477262
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
typedef struct {
4+
unsigned long long f1;
5+
unsigned long long f2;
6+
} SomeCStruct;
7+
8+
static inline SomeCStruct createSomeCStruct() {
9+
SomeCStruct s;
10+
s.f1 = 1;
11+
s.f2 = 2;
12+
return s;
13+
}
14+
15+
typedef enum {
16+
caseA,
17+
caseB,
18+
caseC
19+
} SomeCEnum;
20+
21+
static inline SomeCEnum createSomeCEnum() {
22+
return caseA;
23+
}
24+
25+
#define SWIFT_ENUM(_type, _name) enum _name : _type
26+
27+
typedef SWIFT_ENUM(unsigned short, SomeNSEnum) {
28+
someCaseA,
29+
someCaseB,
30+
} SomeNSEnum;
31+
32+
static inline SomeNSEnum createSomeNSEnum() {
33+
return someCaseB;
34+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// RUN: %target-run-simple-swift(-import-objc-header %S/Inputs/existential_foreign.h -enable-experimental-feature EmbeddedExistentials -enable-experimental-feature Embedded -parse-as-library -wmo) | %FileCheck %s --check-prefix=OUTPUT
2+
// RUN: %target-run-simple-swift(-import-objc-header %S/Inputs/existential_foreign.h -enable-experimental-feature EmbeddedExistentials -enable-experimental-feature Embedded -parse-as-library -wmo -O) | %FileCheck %s --check-prefix=OUTPUT
3+
4+
// REQUIRES: swift_in_compiler
5+
// REQUIRES: executable_test
6+
// REQUIRES: optimized_stdlib
7+
// REQUIRES: swift_feature_Embedded
8+
// REQUIRES: swift_feature_EmbeddedExistentials
9+
10+
protocol P {
11+
func printme()
12+
}
13+
14+
protocol Q {
15+
associatedtype Printable : P
16+
17+
func getPrintable() -> Printable
18+
}
19+
20+
extension SomeCStruct : P {
21+
func printme() {
22+
print("SomeCStruct: \(self.f1), \(self.f2)")
23+
}
24+
}
25+
26+
extension SomeCEnum : P {
27+
func printme() {
28+
switch self {
29+
case caseA:
30+
print("SomeCEnum: .caseA")
31+
case caseB:
32+
print("SomeCEnum: .caseB")
33+
case caseC:
34+
print("SomeCEnum: .caseC")
35+
default:
36+
print("SomeCEnum: default")
37+
}
38+
}
39+
}
40+
41+
struct SomeCStructContainer : Q {
42+
let s: SomeCStruct
43+
44+
init() {
45+
self.s = createSomeCStruct()
46+
}
47+
48+
func getPrintable() -> SomeCStruct {
49+
return s
50+
}
51+
}
52+
53+
struct SomeCEnumContainer : Q {
54+
let s: SomeCEnum
55+
56+
init() {
57+
self.s = createSomeCEnum()
58+
}
59+
60+
func getPrintable() -> SomeCEnum {
61+
return s
62+
}
63+
}
64+
65+
extension SomeNSEnum : P {
66+
func printme() {
67+
switch self {
68+
case .someCaseA:
69+
print("SomeNSEnum: .someCaseA")
70+
case .someCaseB:
71+
print("SomeNSEnum: .someCaseB")
72+
}
73+
}
74+
}
75+
76+
struct SomeNSEnumContainer : Q {
77+
let s: SomeNSEnum
78+
79+
init() {
80+
self.s = createSomeNSEnum()
81+
}
82+
83+
func getPrintable() -> SomeNSEnum {
84+
return s
85+
}
86+
}
87+
88+
@main
89+
struct Main {
90+
static func main() {
91+
92+
let a: [any Q] = [ SomeCStructContainer(), SomeCEnumContainer(), SomeNSEnumContainer() ]
93+
94+
for x0 in a {
95+
let x = x0.getPrintable()
96+
x.printme()
97+
// OUTPUT: SomeCStruct: 1, 2
98+
// OUTPUT: SomeCEnum: .caseA
99+
// OUTPUT: SomeNSEnum: .someCaseB
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)