Skip to content

Commit 0f3cf62

Browse files
committed
Use @abi attribute in mangling
What’s implemented now is actually *far* more thorough than what the surface syntax can currently express, mainly because I can’t apply @abi to nominal types yet.
1 parent c91cf69 commit 0f3cf62

File tree

4 files changed

+208
-6
lines changed

4 files changed

+208
-6
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ class ASTMangler : public Mangler {
209209
return tryMangleSubstitution(type.getPointer());
210210
}
211211

212+
protected:
213+
using Mangler::addSubstitution;
214+
void addSubstitution(const Decl *decl);
215+
216+
using Mangler::tryMangleSubstitution;
217+
bool tryMangleSubstitution(const Decl *decl);
218+
219+
public:
212220
std::string mangleClosureEntity(const AbstractClosureExpr *closure,
213221
SymbolKind SKind);
214222

lib/AST/ASTMangler.cpp

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,54 @@
6666
using namespace swift;
6767
using namespace swift::Mangle;
6868

69+
template<typename DeclType>
70+
static DeclType *getABIDecl(DeclType *D) {
71+
if (!D)
72+
return nullptr;
73+
74+
auto abiRole = ABIRoleInfo(D);
75+
if (!abiRole.providesABI())
76+
return abiRole.getCounterpart();
77+
return nullptr;
78+
}
79+
80+
static std::optional<ASTMangler::SymbolicReferent>
81+
getABIDecl(ASTMangler::SymbolicReferent ref) {
82+
switch (ref.getKind()) {
83+
case ASTMangler::SymbolicReferent::NominalType:
84+
if (auto abiTypeDecl = getABIDecl(ref.getNominalType())) {
85+
return ASTMangler::SymbolicReferent(abiTypeDecl);
86+
}
87+
break;
88+
89+
case ASTMangler::SymbolicReferent::OpaqueType:
90+
if (auto abiTypeDecl = getABIDecl(ref.getOpaqueType())) {
91+
return ASTMangler::SymbolicReferent(abiTypeDecl);
92+
}
93+
break;
94+
95+
case ASTMangler::SymbolicReferent::ExtendedExistentialTypeShape:
96+
// Do nothing; mangling will use the underlying ABI decls in the end.
97+
break;
98+
}
99+
100+
return std::nullopt;
101+
}
102+
103+
void ASTMangler::addSubstitution(const Decl *decl) {
104+
if (auto abiDecl = getABIDecl(decl)) {
105+
return addSubstitution(abiDecl);
106+
}
107+
return Mangler::addSubstitution(decl);
108+
}
109+
110+
bool ASTMangler::tryMangleSubstitution(const Decl *decl) {
111+
if (auto abiDecl = getABIDecl(decl)) {
112+
return tryMangleSubstitution(abiDecl);
113+
}
114+
return Mangler::tryMangleSubstitution(decl);
115+
}
116+
69117
bool ASTMangler::inversesAllowed(const Decl *decl) {
70118
if (!decl)
71119
return true;
@@ -302,6 +350,10 @@ std::string ASTMangler::mangleClosureWitnessThunk(
302350
}
303351

304352
std::string ASTMangler::mangleGlobalVariableFull(const VarDecl *decl) {
353+
if (auto abiDecl = getABIDecl(decl)) {
354+
return mangleGlobalVariableFull(abiDecl);
355+
}
356+
305357
// Clang globals get mangled using Clang's mangler.
306358
if (auto clangDecl =
307359
dyn_cast_or_null<clang::DeclaratorDecl>(decl->getClangDecl())) {
@@ -431,6 +483,10 @@ std::string ASTMangler::mangleGlobalInit(const PatternBindingDecl *pd,
431483
Pattern *pattern = pd->getPattern(pbdEntry);
432484
bool first = true;
433485
pattern->forEachVariable([&](VarDecl *D) {
486+
if (auto abiD = getABIDecl(D)) {
487+
D = abiD;
488+
}
489+
434490
if (first) {
435491
BaseEntitySignature base(D);
436492
appendContextOf(D, base);
@@ -519,6 +575,10 @@ std::string ASTMangler::mangleAutoDiffLinearMap(
519575

520576
void ASTMangler::beginManglingWithAutoDiffOriginalFunction(
521577
const AbstractFunctionDecl *afd) {
578+
if (auto abiAFD = getABIDecl(afd)) {
579+
return beginManglingWithAutoDiffOriginalFunction(abiAFD);
580+
}
581+
522582
if (auto *attr = afd->getAttrs().getAttribute<SILGenNameAttr>()) {
523583
beginManglingWithoutPrefix();
524584
appendOperator(attr->Name);
@@ -852,6 +912,10 @@ void ASTMangler::appendAnyDecl(const ValueDecl *Decl) {
852912
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
853913
appendAnyGenericType(GTD);
854914
} else if (isa<AssociatedTypeDecl>(Decl)) {
915+
if (auto abiDecl = getABIDecl(Decl)) {
916+
return appendAnyDecl(abiDecl);
917+
}
918+
855919
BaseEntitySignature base(Decl);
856920
appendContextOf(Decl, base);
857921
appendDeclName(Decl);
@@ -904,6 +968,10 @@ std::string ASTMangler::mangleAccessorEntityAsUSR(AccessorKind kind,
904968
}
905969

906970
std::string ASTMangler::mangleLocalTypeDecl(const TypeDecl *type) {
971+
if (auto abiType = getABIDecl(type)) {
972+
return mangleLocalTypeDecl(abiType);
973+
}
974+
907975
beginManglingWithoutPrefix();
908976
AllowNamelessEntities = true;
909977
OptimizeProtocolNames = false;
@@ -954,6 +1022,10 @@ std::string ASTMangler::mangleHasSymbolQuery(const ValueDecl *Decl) {
9541022
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
9551023
appendAnyGenericType(GTD);
9561024
} else if (isa<AssociatedTypeDecl>(Decl)) {
1025+
if (auto abiDecl = getABIDecl(Decl)) {
1026+
Decl = abiDecl;
1027+
}
1028+
9571029
BaseEntitySignature nullBase(nullptr);
9581030
appendContextOf(Decl, nullBase);
9591031
appendDeclName(Decl);
@@ -1061,6 +1133,7 @@ getOverriddenSwiftProtocolObjCName(const ValueDecl *decl,
10611133
}
10621134

10631135
void ASTMangler::appendDeclName(const ValueDecl *decl, DeclBaseName name) {
1136+
ASSERT(!getABIDecl(decl) && "caller should make sure we get ABI decls");
10641137
if (name.empty())
10651138
name = decl->getBaseName();
10661139
assert(!name.isSpecial() && "Cannot print special names");
@@ -1196,6 +1269,10 @@ void ASTMangler::appendExistentialLayout(
11961269
bool DroppedRequiresClass = false;
11971270
bool SawRequiresClass = false;
11981271
for (auto proto : layout.getProtocols()) {
1272+
if (auto abiProto = getABIDecl(proto)) {
1273+
proto = abiProto;
1274+
}
1275+
11991276
// Skip requirements to conform to an invertible protocols.
12001277
// We only mangle inverse requirements, but as a constrained existential.
12011278
if (proto->getInvertibleProtocolKind())
@@ -1553,6 +1630,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15531630
Decl = typeAlias->getDecl();
15541631
else
15551632
Decl = type->getAnyGeneric();
1633+
if (auto abiDecl = getABIDecl(Decl)) {
1634+
Decl = abiDecl;
1635+
}
15561636
if (shouldMangleAsGeneric(type)) {
15571637
// Try to mangle the entire name as a substitution.
15581638
if (tryMangleTypeSubstitution(tybase, sig))
@@ -2050,6 +2130,11 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
20502130
Type type,
20512131
GenericSignature sig,
20522132
const ValueDecl *forDecl) {
2133+
if (auto abiShapeReferent = getABIDecl(shapeReferent)) {
2134+
return appendSymbolicExtendedExistentialType(abiShapeReferent.value(), type,
2135+
sig, forDecl);
2136+
}
2137+
20532138
assert(shapeReferent.getKind() ==
20542139
SymbolicReferent::ExtendedExistentialTypeShape);
20552140
assert(canSymbolicReference(shapeReferent));
@@ -2581,6 +2666,7 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25812666
void ASTMangler::appendModule(const ModuleDecl *module,
25822667
StringRef useModuleName) {
25832668
assert(!module->getParent() && "cannot mangle nested modules!");
2669+
ASSERT(!getABIDecl(module));
25842670

25852671
// Use the module real name in mangling; this is the physical name
25862672
// of the module on-disk, which can be different if -module-alias is
@@ -2639,6 +2725,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
26392725
bool allowStandardSubstitution) {
26402726
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
26412727

2728+
if (auto abiProtocol = getABIDecl(protocol)) {
2729+
return appendProtocolName(abiProtocol, allowStandardSubstitution);
2730+
}
2731+
26422732
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
26432733
return;
26442734

@@ -2700,6 +2790,10 @@ ASTMangler::getClangDeclForMangling(const ValueDecl *vd) {
27002790
}
27012791

27022792
void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
2793+
if (auto abiReferent = getABIDecl(referent)) {
2794+
return appendSymbolicReference(abiReferent.value());
2795+
}
2796+
27032797
// Drop in a placeholder. The real reference value has to be filled in during
27042798
// lowering to IR.
27052799
auto offset = Buffer.str().size();
@@ -2833,6 +2927,10 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
28332927
void ASTMangler::appendExtension(const ExtensionDecl* ext,
28342928
BaseEntitySignature &base,
28352929
StringRef useModuleName) {
2930+
if (auto abiExt = getABIDecl(ext)) {
2931+
return appendExtension(abiExt, base, useModuleName);
2932+
}
2933+
28362934
auto decl = ext->getExtendedNominal();
28372935
// Recover from erroneous extension.
28382936
if (!decl)
@@ -2883,6 +2981,10 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
28832981

28842982
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl,
28852983
BaseEntitySignature &base) {
2984+
if (auto abiDecl = getABIDecl(decl)) {
2985+
return appendAnyGenericType(abiDecl);
2986+
}
2987+
28862988
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
28872989

28882990
if (nominal && isa<BuiltinTupleDecl>(nominal))
@@ -3795,6 +3897,10 @@ ASTMangler::dropProtocolsFromAssociatedTypes(Type type,
37953897
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37963898
GenericSignature sig) {
37973899
if (auto assocTy = dmt->getAssocType()) {
3900+
if (auto abiAssocTy = getABIDecl(assocTy)) {
3901+
assocTy = abiAssocTy;
3902+
}
3903+
37983904
appendIdentifier(assocTy->getName().str());
37993905

38003906
// If the base type is known to have a single protocol conformance
@@ -3901,6 +4007,10 @@ CanType ASTMangler::getDeclTypeForMangling(
39014007
const ValueDecl *decl,
39024008
GenericSignature &genericSig,
39034009
GenericSignature &parentGenericSig) {
4010+
if (auto abiDecl = getABIDecl(decl)) {
4011+
return getDeclTypeForMangling(abiDecl, genericSig, parentGenericSig);
4012+
}
4013+
39044014
genericSig = GenericSignature();
39054015
parentGenericSig = GenericSignature();
39064016

@@ -4000,6 +4110,10 @@ bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
40004110

40014111
void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
40024112
bool isAllocating) {
4113+
if (auto abiCtor = getABIDecl(ctor)) {
4114+
return appendConstructorEntity(abiCtor, isAllocating);
4115+
}
4116+
40034117
BaseEntitySignature base(ctor);
40044118
appendContextOf(ctor, base);
40054119
appendDeclType(ctor, base);
@@ -4013,6 +4127,10 @@ void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
40134127

40144128
void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
40154129
DestructorKind kind) {
4130+
if (auto abiDtor = getABIDecl(dtor)) {
4131+
return appendDestructorEntity(abiDtor, kind);
4132+
}
4133+
40164134
BaseEntitySignature base(dtor);
40174135
appendContextOf(dtor, base);
40184136
switch (kind) {
@@ -4031,6 +4149,10 @@ void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
40314149
void ASTMangler::appendAccessorEntity(StringRef accessorKindCode,
40324150
const AbstractStorageDecl *decl,
40334151
bool isStatic) {
4152+
if (auto abiDecl = getABIDecl(decl)) {
4153+
return appendAccessorEntity(accessorKindCode, abiDecl, isStatic);
4154+
}
4155+
40344156
BaseEntitySignature base(decl);
40354157
appendContextOf(decl, base);
40364158
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
@@ -4058,6 +4180,10 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40584180
BaseEntitySignature &base,
40594181
StringRef EntityOp,
40604182
bool isStatic) {
4183+
if (auto abiDecl = getABIDecl(decl)) {
4184+
return appendEntity(abiDecl, base, EntityOp, isStatic);
4185+
}
4186+
40614187
appendContextOf(decl, base);
40624188
appendDeclName(decl);
40634189
appendDeclType(decl, base);
@@ -4069,7 +4195,11 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40694195
void ASTMangler::appendEntity(const ValueDecl *decl) {
40704196
assert(!isa<ConstructorDecl>(decl));
40714197
assert(!isa<DestructorDecl>(decl));
4072-
4198+
4199+
if (auto abiDecl = getABIDecl(decl)) {
4200+
return appendEntity(abiDecl);
4201+
}
4202+
40734203
// Handle accessors specially, they are mangled as modifiers on the accessed
40744204
// declaration.
40754205
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -4424,6 +4554,10 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
44244554

44254555
void ASTMangler::appendDistributedThunk(
44264556
const AbstractFunctionDecl *thunk, bool asReference) {
4557+
if (auto abiThunk = getABIDecl(thunk)) {
4558+
return appendDistributedThunk(abiThunk, asReference);
4559+
}
4560+
44274561
// Marker protocols cannot be checked at runtime, so there is no point
44284562
// in recording them for distributed thunks.
44294563
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
@@ -4486,6 +4620,9 @@ void ASTMangler::appendDistributedThunk(
44864620
if (stubClassLookupResults.size() > 0) {
44874621
stubActorDecl =
44884622
dyn_cast_or_null<NominalTypeDecl>(stubClassLookupResults.front());
4623+
if (auto abiStub = getABIDecl(stubActorDecl)) {
4624+
stubActorDecl = abiStub;
4625+
}
44894626
}
44904627
}
44914628

@@ -4505,7 +4642,11 @@ void ASTMangler::appendDistributedThunk(
45054642
"mangled as thunks");
45064643
// A distributed getter is mangled as the name of its storage (i.e. "the
45074644
// var")
4508-
appendIdentifier(accessor->getStorage()->getBaseIdentifier().str());
4645+
auto storage = accessor->getStorage();
4646+
if (auto abiStorage = getABIDecl(storage)) {
4647+
storage = abiStorage;
4648+
}
4649+
appendIdentifier(storage->getBaseIdentifier().str());
45094650
} else {
45104651
appendIdentifier(thunk->getBaseIdentifier().str());
45114652
}
@@ -4812,6 +4953,10 @@ getPrecheckedLocalContextDiscriminator(const Decl *decl, Identifier name) {
48124953

48134954
std::string ASTMangler::mangleAttachedMacroExpansion(
48144955
const Decl *decl, CustomAttr *attr, MacroRole role) {
4956+
if (auto abiDecl = getABIDecl(decl)) {
4957+
return mangleAttachedMacroExpansion(decl, attr, role);
4958+
}
4959+
48154960
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
48164961
BaseEntitySignature nullBase(nullptr);
48174962

@@ -4926,6 +5071,7 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
49265071
static void gatherExistentialRequirements(SmallVectorImpl<Requirement> &reqs,
49275072
ParameterizedProtocolType *PPT) {
49285073
auto protoTy = PPT->getBaseType();
5074+
ASSERT(!getABIDecl(protoTy->getDecl()) && "need to figure out behavior");
49295075
PPT->getRequirements(protoTy->getDecl()->getSelfInterfaceType(), reqs);
49305076
}
49315077

@@ -4946,6 +5092,7 @@ static void extractExistentialInverseRequirements(
49465092
for (auto ip : PCT->getInverses()) {
49475093
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
49485094
assert(proto);
5095+
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
49495096
inverses.push_back({existentialSelf, proto, SourceLoc()});
49505097
}
49515098
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
318318
}
319319
}
320320

321+
// TODO: Diagnose if Protocol::isMarkerProtocol() - contradiction in terms
322+
// (and mangler can't handle invertible protocols with @abi)
323+
321324
// TODO: Validate more
322325
// FIXME: The list of properties that have to match is practically endless
323326
// and will grow as new features are added to the compiler. We might want to

0 commit comments

Comments
 (0)