Skip to content

Commit 1faa099

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 bc700b2 commit 1faa099

File tree

4 files changed

+208
-5
lines changed

4 files changed

+208
-5
lines changed

include/swift/AST/ASTMangler.h

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

205+
protected:
206+
using Mangler::addSubstitution;
207+
void addSubstitution(const Decl *decl);
208+
209+
using Mangler::tryMangleSubstitution;
210+
bool tryMangleSubstitution(const Decl *decl);
211+
212+
public:
205213
std::string mangleClosureEntity(const AbstractClosureExpr *closure,
206214
SymbolKind SKind);
207215

lib/AST/ASTMangler.cpp

Lines changed: 150 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())) {
@@ -427,6 +479,10 @@ std::string ASTMangler::mangleGlobalInit(const PatternBindingDecl *pd,
427479
Pattern *pattern = pd->getPattern(pbdEntry);
428480
bool first = true;
429481
pattern->forEachVariable([&](VarDecl *D) {
482+
if (auto abiD = getABIDecl(D)) {
483+
D = abiD;
484+
}
485+
430486
if (first) {
431487
BaseEntitySignature base(D);
432488
appendContextOf(D, base);
@@ -515,6 +571,10 @@ std::string ASTMangler::mangleAutoDiffLinearMap(
515571

516572
void ASTMangler::beginManglingWithAutoDiffOriginalFunction(
517573
const AbstractFunctionDecl *afd) {
574+
if (auto abiAFD = getABIDecl(afd)) {
575+
return beginManglingWithAutoDiffOriginalFunction(abiAFD);
576+
}
577+
518578
if (auto *attr = afd->getAttrs().getAttribute<SILGenNameAttr>()) {
519579
beginManglingWithoutPrefix();
520580
appendOperator(attr->Name);
@@ -848,6 +908,10 @@ void ASTMangler::appendAnyDecl(const ValueDecl *Decl) {
848908
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
849909
appendAnyGenericType(GTD);
850910
} else if (isa<AssociatedTypeDecl>(Decl)) {
911+
if (auto abiDecl = getABIDecl(Decl)) {
912+
return appendAnyDecl(abiDecl);
913+
}
914+
851915
BaseEntitySignature base(Decl);
852916
appendContextOf(Decl, base);
853917
appendDeclName(Decl);
@@ -900,6 +964,10 @@ std::string ASTMangler::mangleAccessorEntityAsUSR(AccessorKind kind,
900964
}
901965

902966
std::string ASTMangler::mangleLocalTypeDecl(const TypeDecl *type) {
967+
if (auto abiType = getABIDecl(type)) {
968+
return mangleLocalTypeDecl(abiType);
969+
}
970+
903971
beginManglingWithoutPrefix();
904972
AllowNamelessEntities = true;
905973
OptimizeProtocolNames = false;
@@ -950,6 +1018,10 @@ std::string ASTMangler::mangleHasSymbolQuery(const ValueDecl *Decl) {
9501018
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
9511019
appendAnyGenericType(GTD);
9521020
} else if (isa<AssociatedTypeDecl>(Decl)) {
1021+
if (auto abiDecl = getABIDecl(Decl)) {
1022+
Decl = abiDecl;
1023+
}
1024+
9531025
BaseEntitySignature nullBase(nullptr);
9541026
appendContextOf(Decl, nullBase);
9551027
appendDeclName(Decl);
@@ -1057,6 +1129,7 @@ getOverriddenSwiftProtocolObjCName(const ValueDecl *decl,
10571129
}
10581130

10591131
void ASTMangler::appendDeclName(const ValueDecl *decl, DeclBaseName name) {
1132+
ASSERT(!getABIDecl(decl) && "caller should make sure we get ABI decls");
10601133
if (name.empty())
10611134
name = decl->getBaseName();
10621135
assert(!name.isSpecial() && "Cannot print special names");
@@ -1192,6 +1265,10 @@ void ASTMangler::appendExistentialLayout(
11921265
bool DroppedRequiresClass = false;
11931266
bool SawRequiresClass = false;
11941267
for (auto proto : layout.getProtocols()) {
1268+
if (auto abiProto = getABIDecl(proto)) {
1269+
proto = abiProto;
1270+
}
1271+
11951272
// Skip requirements to conform to an invertible protocols.
11961273
// We only mangle inverse requirements, but as a constrained existential.
11971274
if (proto->getInvertibleProtocolKind())
@@ -1539,6 +1616,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15391616
Decl = typeAlias->getDecl();
15401617
else
15411618
Decl = type->getAnyGeneric();
1619+
if (auto abiDecl = getABIDecl(Decl)) {
1620+
Decl = abiDecl;
1621+
}
15421622
if (shouldMangleAsGeneric(type)) {
15431623
// Try to mangle the entire name as a substitution.
15441624
if (tryMangleTypeSubstitution(tybase, sig))
@@ -2020,6 +2100,11 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
20202100
Type type,
20212101
GenericSignature sig,
20222102
const ValueDecl *forDecl) {
2103+
if (auto abiShapeReferent = getABIDecl(shapeReferent)) {
2104+
return appendSymbolicExtendedExistentialType(abiShapeReferent.value(), type,
2105+
sig, forDecl);
2106+
}
2107+
20232108
assert(shapeReferent.getKind() ==
20242109
SymbolicReferent::ExtendedExistentialTypeShape);
20252110
assert(canSymbolicReference(shapeReferent));
@@ -2545,6 +2630,7 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25452630
void ASTMangler::appendModule(const ModuleDecl *module,
25462631
StringRef useModuleName) {
25472632
assert(!module->getParent() && "cannot mangle nested modules!");
2633+
ASSERT(!getABIDecl(module));
25482634

25492635
// Use the module real name in mangling; this is the physical name
25502636
// of the module on-disk, which can be different if -module-alias is
@@ -2603,6 +2689,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
26032689
bool allowStandardSubstitution) {
26042690
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
26052691

2692+
if (auto abiProtocol = getABIDecl(protocol)) {
2693+
return appendProtocolName(abiProtocol, allowStandardSubstitution);
2694+
}
2695+
26062696
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
26072697
return;
26082698

@@ -2664,6 +2754,10 @@ ASTMangler::getClangDeclForMangling(const ValueDecl *vd) {
26642754
}
26652755

26662756
void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
2757+
if (auto abiReferent = getABIDecl(referent)) {
2758+
return appendSymbolicReference(abiReferent.value());
2759+
}
2760+
26672761
// Drop in a placeholder. The real reference value has to be filled in during
26682762
// lowering to IR.
26692763
auto offset = Buffer.str().size();
@@ -2797,6 +2891,10 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
27972891
void ASTMangler::appendExtension(const ExtensionDecl* ext,
27982892
BaseEntitySignature &base,
27992893
StringRef useModuleName) {
2894+
if (auto abiExt = getABIDecl(ext)) {
2895+
return appendExtension(abiExt, base, useModuleName);
2896+
}
2897+
28002898
auto decl = ext->getExtendedNominal();
28012899
// Recover from erroneous extension.
28022900
if (!decl)
@@ -2847,6 +2945,10 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
28472945

28482946
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl,
28492947
BaseEntitySignature &base) {
2948+
if (auto abiDecl = getABIDecl(decl)) {
2949+
return appendAnyGenericType(abiDecl);
2950+
}
2951+
28502952
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
28512953

28522954
if (nominal && isa<BuiltinTupleDecl>(nominal))
@@ -3745,6 +3847,10 @@ ASTMangler::dropProtocolsFromAssociatedTypes(Type type,
37453847
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37463848
GenericSignature sig) {
37473849
if (auto assocTy = dmt->getAssocType()) {
3850+
if (auto abiAssocTy = getABIDecl(assocTy)) {
3851+
assocTy = abiAssocTy;
3852+
}
3853+
37483854
appendIdentifier(assocTy->getName().str());
37493855

37503856
// If the base type is known to have a single protocol conformance
@@ -3851,6 +3957,10 @@ CanType ASTMangler::getDeclTypeForMangling(
38513957
const ValueDecl *decl,
38523958
GenericSignature &genericSig,
38533959
GenericSignature &parentGenericSig) {
3960+
if (auto abiDecl = getABIDecl(decl)) {
3961+
return getDeclTypeForMangling(abiDecl, genericSig, parentGenericSig);
3962+
}
3963+
38543964
genericSig = GenericSignature();
38553965
parentGenericSig = GenericSignature();
38563966

@@ -3950,6 +4060,10 @@ bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
39504060

39514061
void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39524062
bool isAllocating) {
4063+
if (auto abiCtor = getABIDecl(ctor)) {
4064+
return appendConstructorEntity(abiCtor, isAllocating);
4065+
}
4066+
39534067
BaseEntitySignature base(ctor);
39544068
appendContextOf(ctor, base);
39554069
appendDeclType(ctor, base);
@@ -3963,6 +4077,10 @@ void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39634077

39644078
void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39654079
DestructorKind kind) {
4080+
if (auto abiDtor = getABIDecl(dtor)) {
4081+
return appendDestructorEntity(abiDtor, kind);
4082+
}
4083+
39664084
BaseEntitySignature base(dtor);
39674085
appendContextOf(dtor, base);
39684086
switch (kind) {
@@ -3981,6 +4099,10 @@ void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39814099
void ASTMangler::appendAccessorEntity(StringRef accessorKindCode,
39824100
const AbstractStorageDecl *decl,
39834101
bool isStatic) {
4102+
if (auto abiDecl = getABIDecl(decl)) {
4103+
return appendAccessorEntity(accessorKindCode, abiDecl, isStatic);
4104+
}
4105+
39844106
BaseEntitySignature base(decl);
39854107
appendContextOf(decl, base);
39864108
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
@@ -4008,6 +4130,10 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40084130
BaseEntitySignature &base,
40094131
StringRef EntityOp,
40104132
bool isStatic) {
4133+
if (auto abiDecl = getABIDecl(decl)) {
4134+
return appendEntity(abiDecl, base, EntityOp, isStatic);
4135+
}
4136+
40114137
appendContextOf(decl, base);
40124138
appendDeclName(decl);
40134139
appendDeclType(decl, base);
@@ -4019,7 +4145,11 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40194145
void ASTMangler::appendEntity(const ValueDecl *decl) {
40204146
assert(!isa<ConstructorDecl>(decl));
40214147
assert(!isa<DestructorDecl>(decl));
4022-
4148+
4149+
if (auto abiDecl = getABIDecl(decl)) {
4150+
return appendEntity(abiDecl);
4151+
}
4152+
40234153
// Handle accessors specially, they are mangled as modifiers on the accessed
40244154
// declaration.
40254155
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -4379,6 +4509,10 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
43794509

43804510
void ASTMangler::appendDistributedThunk(
43814511
const AbstractFunctionDecl *thunk, bool asReference) {
4512+
if (auto abiThunk = getABIDecl(thunk)) {
4513+
return appendDistributedThunk(abiThunk, asReference);
4514+
}
4515+
43824516
// Marker protocols cannot be checked at runtime, so there is no point
43834517
// in recording them for distributed thunks.
43844518
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
@@ -4425,6 +4559,10 @@ void ASTMangler::appendDistributedThunk(
44254559
};
44264560

44274561
if (auto *P = referenceInProtocolContextOrRequirement()) {
4562+
if (auto abiP = getABIDecl(P)) {
4563+
P = abiP;
4564+
}
4565+
44284566
appendContext(P->getDeclContext(), base,
44294567
thunk->getAlternateModuleName());
44304568
appendIdentifier(Twine("$", P->getNameStr()).str());
@@ -4439,7 +4577,11 @@ void ASTMangler::appendDistributedThunk(
44394577
"mangled as thunks");
44404578
// A distributed getter is mangled as the name of its storage (i.e. "the
44414579
// var")
4442-
appendIdentifier(accessor->getStorage()->getBaseIdentifier().str());
4580+
auto storage = accessor->getStorage();
4581+
if (auto abiStorage = getABIDecl(storage)) {
4582+
storage = abiStorage;
4583+
}
4584+
appendIdentifier(storage->getBaseIdentifier().str());
44434585
} else {
44444586
appendIdentifier(thunk->getBaseIdentifier().str());
44454587
}
@@ -4654,6 +4796,10 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
46544796

46554797
std::string ASTMangler::mangleAttachedMacroExpansion(
46564798
const Decl *decl, CustomAttr *attr, MacroRole role) {
4799+
if (auto abiDecl = getABIDecl(decl)) {
4800+
return mangleAttachedMacroExpansion(decl, attr, role);
4801+
}
4802+
46574803
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
46584804
BaseEntitySignature nullBase(nullptr);
46594805

@@ -4740,6 +4886,7 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
47404886
static void gatherExistentialRequirements(SmallVectorImpl<Requirement> &reqs,
47414887
ParameterizedProtocolType *PPT) {
47424888
auto protoTy = PPT->getBaseType();
4889+
ASSERT(!getABIDecl(protoTy->getDecl()) && "need to figure out behavior");
47434890
PPT->getRequirements(protoTy->getDecl()->getSelfInterfaceType(), reqs);
47444891
}
47454892

@@ -4760,6 +4907,7 @@ static void extractExistentialInverseRequirements(
47604907
for (auto ip : PCT->getInverses()) {
47614908
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
47624909
assert(proto);
4910+
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
47634911
inverses.push_back({existentialSelf, proto, SourceLoc()});
47644912
}
47654913
}

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)