Skip to content

Commit 4e737d4

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 30627db commit 4e737d4

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
@@ -201,6 +201,14 @@ class ASTMangler : public Mangler {
201201
return tryMangleSubstitution(type.getPointer());
202202
}
203203

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

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);
@@ -838,6 +898,10 @@ void ASTMangler::appendAnyDecl(const ValueDecl *Decl) {
838898
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
839899
appendAnyGenericType(GTD);
840900
} else if (isa<AssociatedTypeDecl>(Decl)) {
901+
if (auto abiDecl = getABIDecl(Decl)) {
902+
return appendAnyDecl(abiDecl);
903+
}
904+
841905
BaseEntitySignature base(Decl);
842906
appendContextOf(Decl, base);
843907
appendDeclName(Decl);
@@ -890,6 +954,10 @@ std::string ASTMangler::mangleAccessorEntityAsUSR(AccessorKind kind,
890954
}
891955

892956
std::string ASTMangler::mangleLocalTypeDecl(const TypeDecl *type) {
957+
if (auto abiType = getABIDecl(type)) {
958+
return mangleLocalTypeDecl(abiType);
959+
}
960+
893961
beginManglingWithoutPrefix();
894962
AllowNamelessEntities = true;
895963
OptimizeProtocolNames = false;
@@ -940,6 +1008,10 @@ std::string ASTMangler::mangleHasSymbolQuery(const ValueDecl *Decl) {
9401008
} else if (auto GTD = dyn_cast<GenericTypeDecl>(Decl)) {
9411009
appendAnyGenericType(GTD);
9421010
} else if (isa<AssociatedTypeDecl>(Decl)) {
1011+
if (auto abiDecl = getABIDecl(Decl)) {
1012+
Decl = abiDecl;
1013+
}
1014+
9431015
BaseEntitySignature nullBase(nullptr);
9441016
appendContextOf(Decl, nullBase);
9451017
appendDeclName(Decl);
@@ -1047,6 +1119,7 @@ getOverriddenSwiftProtocolObjCName(const ValueDecl *decl,
10471119
}
10481120

10491121
void ASTMangler::appendDeclName(const ValueDecl *decl, DeclBaseName name) {
1122+
ASSERT(!getABIDecl(decl) && "caller should make sure we get ABI decls");
10501123
if (name.empty())
10511124
name = decl->getBaseName();
10521125
assert(!name.isSpecial() && "Cannot print special names");
@@ -1182,6 +1255,10 @@ void ASTMangler::appendExistentialLayout(
11821255
bool DroppedRequiresClass = false;
11831256
bool SawRequiresClass = false;
11841257
for (auto proto : layout.getProtocols()) {
1258+
if (auto abiProto = getABIDecl(proto)) {
1259+
proto = abiProto;
1260+
}
1261+
11851262
// Skip requirements to conform to an invertible protocols.
11861263
// We only mangle inverse requirements, but as a constrained existential.
11871264
if (proto->getInvertibleProtocolKind())
@@ -1520,6 +1597,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
15201597
Decl = typeAlias->getDecl();
15211598
else
15221599
Decl = type->getAnyGeneric();
1600+
if (auto abiDecl = getABIDecl(Decl)) {
1601+
Decl = abiDecl;
1602+
}
15231603
if (shouldMangleAsGeneric(type)) {
15241604
// Try to mangle the entire name as a substitution.
15251605
if (tryMangleTypeSubstitution(tybase, sig))
@@ -2001,6 +2081,11 @@ void ASTMangler::appendSymbolicExtendedExistentialType(
20012081
Type type,
20022082
GenericSignature sig,
20032083
const ValueDecl *forDecl) {
2084+
if (auto abiShapeReferent = getABIDecl(shapeReferent)) {
2085+
return appendSymbolicExtendedExistentialType(abiShapeReferent.value(), type,
2086+
sig, forDecl);
2087+
}
2088+
20042089
assert(shapeReferent.getKind() ==
20052090
SymbolicReferent::ExtendedExistentialTypeShape);
20062091
assert(canSymbolicReference(shapeReferent));
@@ -2523,6 +2608,7 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25232608
void ASTMangler::appendModule(const ModuleDecl *module,
25242609
StringRef useModuleName) {
25252610
assert(!module->getParent() && "cannot mangle nested modules!");
2611+
ASSERT(!getABIDecl(module));
25262612

25272613
// Use the module real name in mangling; this is the physical name
25282614
// of the module on-disk, which can be different if -module-alias is
@@ -2581,6 +2667,10 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
25812667
bool allowStandardSubstitution) {
25822668
assert(AllowMarkerProtocols || !protocol->isMarkerProtocol());
25832669

2670+
if (auto abiProtocol = getABIDecl(protocol)) {
2671+
return appendProtocolName(abiProtocol, allowStandardSubstitution);
2672+
}
2673+
25842674
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
25852675
return;
25862676

@@ -2642,6 +2732,10 @@ ASTMangler::getClangDeclForMangling(const ValueDecl *vd) {
26422732
}
26432733

26442734
void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
2735+
if (auto abiReferent = getABIDecl(referent)) {
2736+
return appendSymbolicReference(abiReferent.value());
2737+
}
2738+
26452739
// Drop in a placeholder. The real reference value has to be filled in during
26462740
// lowering to IR.
26472741
auto offset = Buffer.str().size();
@@ -2775,6 +2869,10 @@ void ASTMangler::appendContextualInverses(const GenericTypeDecl *contextDecl,
27752869
void ASTMangler::appendExtension(const ExtensionDecl* ext,
27762870
BaseEntitySignature &base,
27772871
StringRef useModuleName) {
2872+
if (auto abiExt = getABIDecl(ext)) {
2873+
return appendExtension(abiExt, base, useModuleName);
2874+
}
2875+
27782876
auto decl = ext->getExtendedNominal();
27792877
// Recover from erroneous extension.
27802878
if (!decl)
@@ -2825,6 +2923,10 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
28252923

28262924
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl,
28272925
BaseEntitySignature &base) {
2926+
if (auto abiDecl = getABIDecl(decl)) {
2927+
return appendAnyGenericType(abiDecl);
2928+
}
2929+
28282930
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
28292931

28302932
if (nominal && isa<BuiltinTupleDecl>(nominal))
@@ -3723,6 +3825,10 @@ ASTMangler::dropProtocolsFromAssociatedTypes(Type type,
37233825
void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37243826
GenericSignature sig) {
37253827
if (auto assocTy = dmt->getAssocType()) {
3828+
if (auto abiAssocTy = getABIDecl(assocTy)) {
3829+
assocTy = abiAssocTy;
3830+
}
3831+
37263832
appendIdentifier(assocTy->getName().str());
37273833

37283834
// If the base type is known to have a single protocol conformance
@@ -3829,6 +3935,10 @@ CanType ASTMangler::getDeclTypeForMangling(
38293935
const ValueDecl *decl,
38303936
GenericSignature &genericSig,
38313937
GenericSignature &parentGenericSig) {
3938+
if (auto abiDecl = getABIDecl(decl)) {
3939+
return getDeclTypeForMangling(abiDecl, genericSig, parentGenericSig);
3940+
}
3941+
38323942
genericSig = GenericSignature();
38333943
parentGenericSig = GenericSignature();
38343944

@@ -3928,6 +4038,10 @@ bool ASTMangler::tryAppendStandardSubstitution(const GenericTypeDecl *decl) {
39284038

39294039
void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39304040
bool isAllocating) {
4041+
if (auto abiCtor = getABIDecl(ctor)) {
4042+
return appendConstructorEntity(abiCtor, isAllocating);
4043+
}
4044+
39314045
BaseEntitySignature base(ctor);
39324046
appendContextOf(ctor, base);
39334047
appendDeclType(ctor, base);
@@ -3941,6 +4055,10 @@ void ASTMangler::appendConstructorEntity(const ConstructorDecl *ctor,
39414055

39424056
void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39434057
DestructorKind kind) {
4058+
if (auto abiDtor = getABIDecl(dtor)) {
4059+
return appendDestructorEntity(abiDtor, kind);
4060+
}
4061+
39444062
BaseEntitySignature base(dtor);
39454063
appendContextOf(dtor, base);
39464064
switch (kind) {
@@ -3959,6 +4077,10 @@ void ASTMangler::appendDestructorEntity(const DestructorDecl *dtor,
39594077
void ASTMangler::appendAccessorEntity(StringRef accessorKindCode,
39604078
const AbstractStorageDecl *decl,
39614079
bool isStatic) {
4080+
if (auto abiDecl = getABIDecl(decl)) {
4081+
return appendAccessorEntity(accessorKindCode, abiDecl, isStatic);
4082+
}
4083+
39624084
BaseEntitySignature base(decl);
39634085
appendContextOf(decl, base);
39644086
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
@@ -3986,6 +4108,10 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
39864108
BaseEntitySignature &base,
39874109
StringRef EntityOp,
39884110
bool isStatic) {
4111+
if (auto abiDecl = getABIDecl(decl)) {
4112+
return appendEntity(abiDecl, base, EntityOp, isStatic);
4113+
}
4114+
39894115
appendContextOf(decl, base);
39904116
appendDeclName(decl);
39914117
appendDeclType(decl, base);
@@ -3997,7 +4123,11 @@ void ASTMangler::appendEntity(const ValueDecl *decl,
39974123
void ASTMangler::appendEntity(const ValueDecl *decl) {
39984124
assert(!isa<ConstructorDecl>(decl));
39994125
assert(!isa<DestructorDecl>(decl));
4000-
4126+
4127+
if (auto abiDecl = getABIDecl(decl)) {
4128+
return appendEntity(abiDecl);
4129+
}
4130+
40014131
// Handle accessors specially, they are mangled as modifiers on the accessed
40024132
// declaration.
40034133
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
@@ -4357,6 +4487,10 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
43574487

43584488
void ASTMangler::appendDistributedThunk(
43594489
const AbstractFunctionDecl *thunk, bool asReference) {
4490+
if (auto abiThunk = getABIDecl(thunk)) {
4491+
return appendDistributedThunk(abiThunk, asReference);
4492+
}
4493+
43604494
// Marker protocols cannot be checked at runtime, so there is no point
43614495
// in recording them for distributed thunks.
43624496
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
@@ -4403,6 +4537,10 @@ void ASTMangler::appendDistributedThunk(
44034537
};
44044538

44054539
if (auto *P = referenceInProtocolContextOrRequirement()) {
4540+
if (auto abiP = getABIDecl(P)) {
4541+
P = abiP;
4542+
}
4543+
44064544
appendContext(P->getDeclContext(), base,
44074545
thunk->getAlternateModuleName());
44084546
appendIdentifier(Twine("$", P->getNameStr()).str());
@@ -4417,7 +4555,11 @@ void ASTMangler::appendDistributedThunk(
44174555
"mangled as thunks");
44184556
// A distributed getter is mangled as the name of its storage (i.e. "the
44194557
// var")
4420-
appendIdentifier(accessor->getStorage()->getBaseIdentifier().str());
4558+
auto storage = accessor->getStorage();
4559+
if (auto abiStorage = getABIDecl(storage)) {
4560+
storage = abiStorage;
4561+
}
4562+
appendIdentifier(storage->getBaseIdentifier().str());
44214563
} else {
44224564
appendIdentifier(thunk->getBaseIdentifier().str());
44234565
}
@@ -4632,6 +4774,10 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
46324774

46334775
std::string ASTMangler::mangleAttachedMacroExpansion(
46344776
const Decl *decl, CustomAttr *attr, MacroRole role) {
4777+
if (auto abiDecl = getABIDecl(decl)) {
4778+
return mangleAttachedMacroExpansion(decl, attr, role);
4779+
}
4780+
46354781
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
46364782
BaseEntitySignature nullBase(nullptr);
46374783

@@ -4718,6 +4864,7 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
47184864
static void gatherExistentialRequirements(SmallVectorImpl<Requirement> &reqs,
47194865
ParameterizedProtocolType *PPT) {
47204866
auto protoTy = PPT->getBaseType();
4867+
ASSERT(!getABIDecl(protoTy->getDecl()) && "need to figure out behavior");
47214868
PPT->getRequirements(protoTy->getDecl()->getSelfInterfaceType(), reqs);
47224869
}
47234870

@@ -4738,6 +4885,7 @@ static void extractExistentialInverseRequirements(
47384885
for (auto ip : PCT->getInverses()) {
47394886
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
47404887
assert(proto);
4888+
ASSERT(!getABIDecl(proto) && "can't use @abi on inverse protocols");
47414889
inverses.push_back({existentialSelf, proto, SourceLoc()});
47424890
}
47434891
}

lib/Sema/TypeCheckAttr.cpp

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

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

0 commit comments

Comments
 (0)