Skip to content

Commit 1ff6967

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 59f83be commit 1ff6967

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())
@@ -1538,6 +1615,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15381615
Decl = typeAlias->getDecl();
15391616
else
15401617
Decl = type->getAnyGeneric();
1618+
if (auto abiDecl = getABIDecl(Decl)) {
1619+
Decl = abiDecl;
1620+
}
15411621
if (shouldMangleAsGeneric(type)) {
15421622
// Try to mangle the entire name as a substitution.
15431623
if (tryMangleTypeSubstitution(tybase, sig))
@@ -2035,6 +2115,11 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
20352115
Type type,
20362116
GenericSignature sig,
20372117
const ValueDecl *forDecl) {
2118+
if (auto abiShapeReferent = getABIDecl(shapeReferent)) {
2119+
return appendSymbolicExtendedExistentialType(abiShapeReferent.value(), type,
2120+
sig, forDecl);
2121+
}
2122+
20382123
assert(shapeReferent.getKind() ==
20392124
SymbolicReferent::ExtendedExistentialTypeShape);
20402125
assert(canSymbolicReference(shapeReferent));
@@ -2560,6 +2645,7 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25602645
void ASTMangler::appendModule(const ModuleDecl *module,
25612646
StringRef useModuleName) {
25622647
assert(!module->getParent() && "cannot mangle nested modules!");
2648+
ASSERT(!getABIDecl(module));
25632649

25642650
// Use the module real name in mangling; this is the physical name
25652651
// of the module on-disk, which can be different if -module-alias is
@@ -2618,6 +2704,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
26182704
bool allowStandardSubstitution) {
26192705
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
26202706

2707+
if (auto abiProtocol = getABIDecl(protocol)) {
2708+
return appendProtocolName(abiProtocol, allowStandardSubstitution);
2709+
}
2710+
26212711
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
26222712
return;
26232713

@@ -2679,6 +2769,10 @@ ASTMangler::getClangDeclForMangling(const ValueDecl *vd) {
26792769
}
26802770

26812771
void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
2772+
if (auto abiReferent = getABIDecl(referent)) {
2773+
return appendSymbolicReference(abiReferent.value());
2774+
}
2775+
26822776
// Drop in a placeholder. The real reference value has to be filled in during
26832777
// lowering to IR.
26842778
auto offset = Buffer.str().size();
@@ -2812,6 +2906,10 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
28122906
void ASTMangler::appendExtension(const ExtensionDecl* ext,
28132907
BaseEntitySignature &base,
28142908
StringRef useModuleName) {
2909+
if (auto abiExt = getABIDecl(ext)) {
2910+
return appendExtension(abiExt, base, useModuleName);
2911+
}
2912+
28152913
auto decl = ext->getExtendedNominal();
28162914
// Recover from erroneous extension.
28172915
if (!decl)
@@ -2862,6 +2960,10 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
28622960

28632961
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl,
28642962
BaseEntitySignature &base) {
2963+
if (auto abiDecl = getABIDecl(decl)) {
2964+
return appendAnyGenericType(abiDecl);
2965+
}
2966+
28652967
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
28662968

28672969
if (nominal && isa<BuiltinTupleDecl>(nominal))
@@ -3774,6 +3876,10 @@ ASTMangler::dropProtocolsFromAssociatedTypes(Type type,
37743876
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37753877
GenericSignature sig) {
37763878
if (auto assocTy = dmt->getAssocType()) {
3879+
if (auto abiAssocTy = getABIDecl(assocTy)) {
3880+
assocTy = abiAssocTy;
3881+
}
3882+
37773883
appendIdentifier(assocTy->getName().str());
37783884

37793885
// If the base type is known to have a single protocol conformance
@@ -3880,6 +3986,10 @@ CanType ASTMangler::getDeclTypeForMangling(
38803986
const ValueDecl *decl,
38813987
GenericSignature &genericSig,
38823988
GenericSignature &parentGenericSig) {
3989+
if (auto abiDecl = getABIDecl(decl)) {
3990+
return getDeclTypeForMangling(abiDecl, genericSig, parentGenericSig);
3991+
}
3992+
38833993
genericSig = GenericSignature();
38843994
parentGenericSig = GenericSignature();
38853995

@@ -3979,6 +4089,10 @@ bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
39794089

39804090
void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39814091
bool isAllocating) {
4092+
if (auto abiCtor = getABIDecl(ctor)) {
4093+
return appendConstructorEntity(abiCtor, isAllocating);
4094+
}
4095+
39824096
BaseEntitySignature base(ctor);
39834097
appendContextOf(ctor, base);
39844098
appendDeclType(ctor, base);
@@ -3992,6 +4106,10 @@ void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39924106

39934107
void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39944108
DestructorKind kind) {
4109+
if (auto abiDtor = getABIDecl(dtor)) {
4110+
return appendDestructorEntity(abiDtor, kind);
4111+
}
4112+
39954113
BaseEntitySignature base(dtor);
39964114
appendContextOf(dtor, base);
39974115
switch (kind) {
@@ -4010,6 +4128,10 @@ void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
40104128
void ASTMangler::appendAccessorEntity(StringRef accessorKindCode,
40114129
const AbstractStorageDecl *decl,
40124130
bool isStatic) {
4131+
if (auto abiDecl = getABIDecl(decl)) {
4132+
return appendAccessorEntity(accessorKindCode, abiDecl, isStatic);
4133+
}
4134+
40134135
BaseEntitySignature base(decl);
40144136
appendContextOf(decl, base);
40154137
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
@@ -4037,6 +4159,10 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40374159
BaseEntitySignature &base,
40384160
StringRef EntityOp,
40394161
bool isStatic) {
4162+
if (auto abiDecl = getABIDecl(decl)) {
4163+
return appendEntity(abiDecl, base, EntityOp, isStatic);
4164+
}
4165+
40404166
appendContextOf(decl, base);
40414167
appendDeclName(decl);
40424168
appendDeclType(decl, base);
@@ -4048,7 +4174,11 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40484174
void ASTMangler::appendEntity(const ValueDecl *decl) {
40494175
assert(!isa<ConstructorDecl>(decl));
40504176
assert(!isa<DestructorDecl>(decl));
4051-
4177+
4178+
if (auto abiDecl = getABIDecl(decl)) {
4179+
return appendEntity(abiDecl);
4180+
}
4181+
40524182
// Handle accessors specially, they are mangled as modifiers on the accessed
40534183
// declaration.
40544184
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -4408,6 +4538,10 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
44084538

44094539
void ASTMangler::appendDistributedThunk(
44104540
const AbstractFunctionDecl *thunk, bool asReference) {
4541+
if (auto abiThunk = getABIDecl(thunk)) {
4542+
return appendDistributedThunk(abiThunk, asReference);
4543+
}
4544+
44114545
// Marker protocols cannot be checked at runtime, so there is no point
44124546
// in recording them for distributed thunks.
44134547
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
@@ -4470,6 +4604,9 @@ void ASTMangler::appendDistributedThunk(
44704604
if (stubClassLookupResults.size() > 0) {
44714605
stubActorDecl =
44724606
dyn_cast_or_null<NominalTypeDecl>(stubClassLookupResults.front());
4607+
if (auto abiStub = getABIDecl(stubActorDecl)) {
4608+
stubActorDecl = abiStub;
4609+
}
44734610
}
44744611
}
44754612

@@ -4489,7 +4626,11 @@ void ASTMangler::appendDistributedThunk(
44894626
"mangled as thunks");
44904627
// A distributed getter is mangled as the name of its storage (i.e. "the
44914628
// var")
4492-
appendIdentifier(accessor->getStorage()->getBaseIdentifier().str());
4629+
auto storage = accessor->getStorage();
4630+
if (auto abiStorage = getABIDecl(storage)) {
4631+
storage = abiStorage;
4632+
}
4633+
appendIdentifier(storage->getBaseIdentifier().str());
44934634
} else {
44944635
appendIdentifier(thunk->getBaseIdentifier().str());
44954636
}
@@ -4705,6 +4846,10 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
47054846

47064847
std::string ASTMangler::mangleAttachedMacroExpansion(
47074848
const Decl *decl, CustomAttr *attr, MacroRole role) {
4849+
if (auto abiDecl = getABIDecl(decl)) {
4850+
return mangleAttachedMacroExpansion(decl, attr, role);
4851+
}
4852+
47084853
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
47094854
BaseEntitySignature nullBase(nullptr);
47104855

@@ -4791,6 +4936,7 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
47914936
static void gatherExistentialRequirements(SmallVectorImpl<Requirement> &reqs,
47924937
ParameterizedProtocolType *PPT) {
47934938
auto protoTy = PPT->getBaseType();
4939+
ASSERT(!getABIDecl(protoTy->getDecl()) && "need to figure out behavior");
47944940
PPT->getRequirements(protoTy->getDecl()->getSelfInterfaceType(), reqs);
47954941
}
47964942

@@ -4811,6 +4957,7 @@ static void extractExistentialInverseRequirements(
48114957
for (auto ip : PCT->getInverses()) {
48124958
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
48134959
assert(proto);
4960+
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
48144961
inverses.push_back({existentialSelf, proto, SourceLoc()});
48154962
}
48164963
}

lib/Sema/TypeCheckAttr.cpp

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

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

0 commit comments

Comments
 (0)