Skip to content

Commit 6b8913d

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 b95b478 commit 6b8913d

File tree

4 files changed

+209
-6
lines changed

4 files changed

+209
-6
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())
@@ -1533,6 +1610,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15331610
Decl = typeAlias->getDecl();
15341611
else
15351612
Decl = type->getAnyGeneric();
1613+
if (auto abiDecl = getABIDecl(Decl)) {
1614+
Decl = abiDecl;
1615+
}
15361616
if (shouldMangleAsGeneric(type)) {
15371617
// Try to mangle the entire name as a substitution.
15381618
if (tryMangleTypeSubstitution(tybase, sig))
@@ -2017,6 +2097,11 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
20172097
Type type,
20182098
GenericSignature sig,
20192099
const ValueDecl *forDecl) {
2100+
if (auto abiShapeReferent = getABIDecl(shapeReferent)) {
2101+
return appendSymbolicExtendedExistentialType(abiShapeReferent.value(), type,
2102+
sig, forDecl);
2103+
}
2104+
20202105
assert(shapeReferent.getKind() ==
20212106
SymbolicReferent::ExtendedExistentialTypeShape);
20222107
assert(canSymbolicReference(shapeReferent));
@@ -2542,6 +2627,7 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25422627
void ASTMangler::appendModule(const ModuleDecl *module,
25432628
StringRef useModuleName) {
25442629
assert(!module->getParent() && "cannot mangle nested modules!");
2630+
ASSERT(!getABIDecl(module));
25452631

25462632
// Use the module real name in mangling; this is the physical name
25472633
// of the module on-disk, which can be different if -module-alias is
@@ -2600,6 +2686,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
26002686
bool allowStandardSubstitution) {
26012687
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
26022688

2689+
if (auto abiProtocol = getABIDecl(protocol)) {
2690+
return appendProtocolName(abiProtocol, allowStandardSubstitution);
2691+
}
2692+
26032693
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
26042694
return;
26052695

@@ -2661,6 +2751,10 @@ ASTMangler::getClangDeclForMangling(const ValueDecl *vd) {
26612751
}
26622752

26632753
void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
2754+
if (auto abiReferent = getABIDecl(referent)) {
2755+
return appendSymbolicReference(abiReferent.value());
2756+
}
2757+
26642758
// Drop in a placeholder. The real reference value has to be filled in during
26652759
// lowering to IR.
26662760
auto offset = Buffer.str().size();
@@ -2794,6 +2888,10 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
27942888
void ASTMangler::appendExtension(const ExtensionDecl* ext,
27952889
BaseEntitySignature &base,
27962890
StringRef useModuleName) {
2891+
if (auto abiExt = getABIDecl(ext)) {
2892+
return appendExtension(abiExt, base, useModuleName);
2893+
}
2894+
27972895
auto decl = ext->getExtendedNominal();
27982896
// Recover from erroneous extension.
27992897
if (!decl)
@@ -2844,6 +2942,10 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
28442942

28452943
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl,
28462944
BaseEntitySignature &base) {
2945+
if (auto abiDecl = getABIDecl(decl)) {
2946+
return appendAnyGenericType(abiDecl);
2947+
}
2948+
28472949
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
28482950

28492951
if (nominal && isa<BuiltinTupleDecl>(nominal))
@@ -3749,6 +3851,10 @@ ASTMangler::dropProtocolsFromAssociatedTypes(Type type,
37493851
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37503852
GenericSignature sig) {
37513853
if (auto assocTy = dmt->getAssocType()) {
3854+
if (auto abiAssocTy = getABIDecl(assocTy)) {
3855+
assocTy = abiAssocTy;
3856+
}
3857+
37523858
appendIdentifier(assocTy->getName().str());
37533859

37543860
// If the base type is known to have a single protocol conformance
@@ -3855,6 +3961,10 @@ CanType ASTMangler::getDeclTypeForMangling(
38553961
const ValueDecl *decl,
38563962
GenericSignature &genericSig,
38573963
GenericSignature &parentGenericSig) {
3964+
if (auto abiDecl = getABIDecl(decl)) {
3965+
return getDeclTypeForMangling(abiDecl, genericSig, parentGenericSig);
3966+
}
3967+
38583968
genericSig = GenericSignature();
38593969
parentGenericSig = GenericSignature();
38603970

@@ -3954,6 +4064,10 @@ bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
39544064

39554065
void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39564066
bool isAllocating) {
4067+
if (auto abiCtor = getABIDecl(ctor)) {
4068+
return appendConstructorEntity(abiCtor, isAllocating);
4069+
}
4070+
39574071
BaseEntitySignature base(ctor);
39584072
appendContextOf(ctor, base);
39594073
appendDeclType(ctor, base);
@@ -3967,6 +4081,10 @@ void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39674081

39684082
void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39694083
DestructorKind kind) {
4084+
if (auto abiDtor = getABIDecl(dtor)) {
4085+
return appendDestructorEntity(abiDtor, kind);
4086+
}
4087+
39704088
BaseEntitySignature base(dtor);
39714089
appendContextOf(dtor, base);
39724090
switch (kind) {
@@ -3985,6 +4103,10 @@ void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39854103
void ASTMangler::appendAccessorEntity(StringRef accessorKindCode,
39864104
const AbstractStorageDecl *decl,
39874105
bool isStatic) {
4106+
if (auto abiDecl = getABIDecl(decl)) {
4107+
return appendAccessorEntity(accessorKindCode, abiDecl, isStatic);
4108+
}
4109+
39884110
BaseEntitySignature base(decl);
39894111
appendContextOf(decl, base);
39904112
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
@@ -4012,6 +4134,10 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40124134
BaseEntitySignature &base,
40134135
StringRef EntityOp,
40144136
bool isStatic) {
4137+
if (auto abiDecl = getABIDecl(decl)) {
4138+
return appendEntity(abiDecl, base, EntityOp, isStatic);
4139+
}
4140+
40154141
appendContextOf(decl, base);
40164142
appendDeclName(decl);
40174143
appendDeclType(decl, base);
@@ -4023,7 +4149,11 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
40234149
void ASTMangler::appendEntity(const ValueDecl *decl) {
40244150
assert(!isa<ConstructorDecl>(decl));
40254151
assert(!isa<DestructorDecl>(decl));
4026-
4152+
4153+
if (auto abiDecl = getABIDecl(decl)) {
4154+
return appendEntity(abiDecl);
4155+
}
4156+
40274157
// Handle accessors specially, they are mangled as modifiers on the accessed
40284158
// declaration.
40294159
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -4383,6 +4513,10 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
43834513

43844514
void ASTMangler::appendDistributedThunk(
43854515
const AbstractFunctionDecl *thunk, bool asReference) {
4516+
if (auto abiThunk = getABIDecl(thunk)) {
4517+
return appendDistributedThunk(abiThunk, asReference);
4518+
}
4519+
43864520
// Marker protocols cannot be checked at runtime, so there is no point
43874521
// in recording them for distributed thunks.
43884522
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
@@ -4429,6 +4563,10 @@ void ASTMangler::appendDistributedThunk(
44294563
};
44304564

44314565
if (auto *P = referenceInProtocolContextOrRequirement()) {
4566+
if (auto abiP = getABIDecl(P)) {
4567+
P = abiP;
4568+
}
4569+
44324570
appendContext(P->getDeclContext(), base,
44334571
thunk->getAlternateModuleName());
44344572
appendIdentifier(Twine("$", P->getNameStr()).str());
@@ -4443,7 +4581,11 @@ void ASTMangler::appendDistributedThunk(
44434581
"mangled as thunks");
44444582
// A distributed getter is mangled as the name of its storage (i.e. "the
44454583
// var")
4446-
appendIdentifier(accessor->getStorage()->getBaseIdentifier().str());
4584+
auto storage = accessor->getStorage();
4585+
if (auto abiStorage = getABIDecl(storage)) {
4586+
storage = abiStorage;
4587+
}
4588+
appendIdentifier(storage->getBaseIdentifier().str());
44474589
} else {
44484590
appendIdentifier(thunk->getBaseIdentifier().str());
44494591
}
@@ -4658,6 +4800,10 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
46584800

46594801
std::string ASTMangler::mangleAttachedMacroExpansion(
46604802
const Decl *decl, CustomAttr *attr, MacroRole role) {
4803+
if (auto abiDecl = getABIDecl(decl)) {
4804+
return mangleAttachedMacroExpansion(decl, attr, role);
4805+
}
4806+
46614807
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
46624808
BaseEntitySignature nullBase(nullptr);
46634809

@@ -4744,6 +4890,7 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
47444890
static void gatherExistentialRequirements(SmallVectorImpl<Requirement> &reqs,
47454891
ParameterizedProtocolType *PPT) {
47464892
auto protoTy = PPT->getBaseType();
4893+
ASSERT(!getABIDecl(protoTy->getDecl()) && "need to figure out behavior");
47474894
PPT->getRequirements(protoTy->getDecl()->getSelfInterfaceType(), reqs);
47484895
}
47494896

@@ -4764,6 +4911,7 @@ static void extractExistentialInverseRequirements(
47644911
for (auto ip : PCT->getInverses()) {
47654912
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
47664913
assert(proto);
4914+
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
47674915
inverses.push_back({existentialSelf, proto, SourceLoc()});
47684916
}
47694917
}

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)