Skip to content

Commit 07d4558

Browse files
committed
[Mangler] Change the Swift mangler into a symbol builder.
This commit changes the Swift mangler from a utility that writes tokens into a stream into a name-builder that has two phases: "building a name", and "ready". This clear separation is needed for the implementation of the compression layer. Users of the mangler can continue to build the name using the mangleXXX methods, but to access the results the users of the mangler need to call the finalize() method. This method can write the result into a stream, like before, or return an std::string.
1 parent c26f97f commit 07d4558

27 files changed

+243
-269
lines changed

include/swift/AST/Mangle.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,18 @@ enum class OperatorFixity {
3535
};
3636

3737

38-
/// A class for mangling declarations.
38+
/// A class for mangling declarations. The Mangler accumulates name fragments
39+
/// with the mangleXXX methods, and the final string is constructed with the
40+
/// `finalize` method, after which the Mangler should not be used.
3941
class Mangler {
4042
struct ArchetypeInfo {
4143
unsigned Depth;
4244
unsigned Index;
4345
};
4446

45-
raw_ostream &Buffer;
47+
llvm::SmallVector<char, 128> Storage;
48+
llvm::raw_svector_ostream Buffer;
49+
4650
llvm::DenseMap<const void *, unsigned> Substitutions;
4751
llvm::DenseMap<const ArchetypeType *, ArchetypeInfo> Archetypes;
4852
CanGenericSignature CurGenericSignature;
@@ -84,14 +88,30 @@ class Mangler {
8488
~ContextStack() { M.ArchetypesDepth = OldDepth; }
8589
};
8690

91+
/// Finish the mangling of the symbol and return the mangled name.
92+
std::string finalize() {
93+
assert(Storage.size() && "Mangling an empty name");
94+
std::string result = std::string(Storage.data(), Storage.size());
95+
Storage.clear();
96+
return result;
97+
}
98+
99+
/// Finish the mangling of the symbol and write the mangled name into
100+
/// \p stream.
101+
void finalize(llvm::raw_ostream &stream) {
102+
assert(Storage.size() && "Mangling an empty name");
103+
stream.write(Storage.data(), Storage.size());
104+
Storage.clear();
105+
}
106+
87107
void setModuleContext(ModuleDecl *M) { Mod = M; }
88108

89109
/// \param DWARFMangling - use the 'Qq' mangling format for
90110
/// archetypes and the 'a' mangling for alias types.
91111
/// \param usePunycode - emit modified Punycode instead of UTF-8.
92-
Mangler(raw_ostream &buffer, bool DWARFMangling = false,
112+
Mangler(bool DWARFMangling = false,
93113
bool usePunycode = true)
94-
: Buffer(buffer), DWARFMangling(DWARFMangling), UsePunycode(usePunycode) {}
114+
: Buffer(Storage), DWARFMangling(DWARFMangling), UsePunycode(usePunycode) {}
95115
void mangleContextOf(const ValueDecl *decl, BindGenerics shouldBind);
96116
void mangleContext(const DeclContext *ctx, BindGenerics shouldBind);
97117
void mangleModule(const ModuleDecl *module);

include/swift/SIL/SILDeclRef.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,7 @@ struct SILDeclRef {
234234
///
235235
/// If 'prefix' is non-empty, it will be used in place of the standard '_T'
236236
/// prefix.
237-
llvm::StringRef mangle(llvm::SmallVectorImpl<char> &buffer,
238-
StringRef prefix = {}) const;
237+
std::string mangle(StringRef prefix = {}) const;
239238

240239
/// True if the SILDeclRef references a function.
241240
bool isFunc() const {

lib/AST/Decl.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,11 +2316,8 @@ ObjCClassKind ClassDecl::checkObjCAncestry() const {
23162316
static StringRef mangleObjCRuntimeName(const NominalTypeDecl *nominal,
23172317
llvm::SmallVectorImpl<char> &buffer) {
23182318
{
2319-
buffer.clear();
2320-
llvm::raw_svector_ostream os(buffer);
2321-
23222319
// Mangle the type.
2323-
Mangle::Mangler mangler(os, false/*dwarf*/, false/*punycode*/);
2320+
Mangle::Mangler mangler(false/*dwarf*/, false/*punycode*/);
23242321

23252322
// We add the "_Tt" prefix to make this a reserved name that will
23262323
// not conflict with any valid Objective-C class or protocol name.
@@ -2334,8 +2331,13 @@ static StringRef mangleObjCRuntimeName(const NominalTypeDecl *nominal,
23342331
} else {
23352332
mangler.mangleProtocolDecl(cast<ProtocolDecl>(NTD));
23362333
}
2334+
2335+
buffer.clear();
2336+
llvm::raw_svector_ostream os(buffer);
2337+
mangler.finalize(os);
23372338
}
23382339

2340+
assert(buffer.size() && "Invalid buffer size");
23392341
return StringRef(buffer.data(), buffer.size());
23402342
}
23412343

lib/AST/Mangle.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,19 +1281,20 @@ void Mangler::mangleType(Type type, ResilienceExpansion explosion,
12811281
Buffer << 'q' << Index(info.Index);
12821282

12831283
{
1284-
// The DWARF output created by Swift is intentionally flat,
1285-
// therefore archetypes are emitted with their DeclContext if
1286-
// they appear at the top level of a type (_Tt).
1287-
// Clone a new, non-DWARF Mangler for the DeclContext.
1288-
Mangler ContextMangler(Buffer, /*DWARFMangling=*/false);
1289-
SmallVector<const void *, 4> SortedSubsts(Substitutions.size());
1290-
for (auto S : Substitutions) SortedSubsts[S.second] = S.first;
1291-
for (auto S : SortedSubsts) ContextMangler.addSubstitution(S);
1292-
for (; relativeDepth > 0; --relativeDepth)
1293-
DC = DC->getParent();
1294-
assert(DC && "no decl context for archetype found");
1295-
if (!DC) return;
1296-
ContextMangler.mangleContext(DC, BindGenerics::None);
1284+
// The DWARF output created by Swift is intentionally flat,
1285+
// therefore archetypes are emitted with their DeclContext if
1286+
// they appear at the top level of a type (_Tt).
1287+
// Clone a new, non-DWARF Mangler for the DeclContext.
1288+
Mangler ContextMangler(/*DWARFMangling=*/false);
1289+
SmallVector<const void *, 4> SortedSubsts(Substitutions.size());
1290+
for (auto S : Substitutions) SortedSubsts[S.second] = S.first;
1291+
for (auto S : SortedSubsts) ContextMangler.addSubstitution(S);
1292+
for (; relativeDepth > 0; --relativeDepth)
1293+
DC = DC->getParent();
1294+
assert(DC && "no decl context for archetype found");
1295+
if (!DC) return;
1296+
ContextMangler.mangleContext(DC, BindGenerics::None);
1297+
ContextMangler.finalize(Buffer);
12971298
}
12981299

12991300
} else {

lib/AST/USRGeneration.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ bool ide::printDeclUSR(const ValueDecl *D, raw_ostream &OS) {
7171
return true;
7272

7373
OS << getUSRSpacePrefix();
74-
Mangler Mangler(OS);
74+
Mangler Mangler;
7575
if (auto Ctor = dyn_cast<ConstructorDecl>(VD)) {
7676
Mangler.mangleConstructorEntity(Ctor, /*isAllocating=*/false,
7777
ResilienceExpansion::Minimal, /*uncurryingLevel=*/0);
@@ -87,6 +87,8 @@ bool ide::printDeclUSR(const ValueDecl *D, raw_ostream &OS) {
8787
Mangler.mangleEntity(VD, ResilienceExpansion::Minimal,
8888
/*uncurryingLevel=*/0);
8989
}
90+
91+
Mangler.finalize(OS);
9092
return false;
9193
}
9294

@@ -108,9 +110,10 @@ bool ide::printAccessorUSR(const AbstractStorageDecl *D, AccessorKind AccKind,
108110

109111
AbstractStorageDecl *SD = const_cast<AbstractStorageDecl*>(D);
110112
OS << getUSRSpacePrefix();
111-
Mangler Mangler(OS);
113+
Mangler Mangler;
112114
Mangler.mangleAccessorEntity(AccKind, AddressorKind::NotAddressor,
113115
SD, ResilienceExpansion::Minimal);
116+
Mangler.finalize(OS);
114117
return false;
115118
}
116119

lib/AST/Verifier.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,13 +2603,9 @@ struct ASTNodeBase {};
26032603
}
26042604

26052605
void checkMangling(ValueDecl *D) {
2606-
llvm::SmallString<32> Buf;
2607-
llvm::raw_svector_ostream OS(Buf);
2608-
{
2609-
Mangle::Mangler Mangler(OS);
2606+
Mangle::Mangler Mangler;
26102607
Mangler.mangleDeclName(D);
2611-
}
2612-
if (OS.str().empty()) {
2608+
if (Mangler.finalize().empty()) {
26132609
Out << "Mangler gave empty string for a ValueDecl";
26142610
abort();
26152611
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,14 +1133,9 @@ StringRef IRGenDebugInfo::getMangledName(DebugTypeInfo DbgTy) {
11331133
if (MetadataTypeDecl && DbgTy.getDecl() == MetadataTypeDecl)
11341134
return BumpAllocatedString(DbgTy.getDecl()->getName().str());
11351135

1136-
llvm::SmallString<160> Buffer;
1137-
{
1138-
llvm::raw_svector_ostream S(Buffer);
1139-
Mangle::Mangler M(S, /* DWARF */ true);
1140-
M.mangleTypeForDebugger(DbgTy.getType(), DbgTy.getDeclContext());
1141-
}
1142-
assert(!Buffer.empty() && "mangled name came back empty");
1143-
return BumpAllocatedString(Buffer);
1136+
Mangle::Mangler M(/* DWARF */ true);
1137+
M.mangleTypeForDebugger(DbgTy.getType(), DbgTy.getDeclContext());
1138+
return BumpAllocatedString(M.finalize());
11441139
}
11451140

11461141
/// Create a member of a struct, class, tuple, or enum.

0 commit comments

Comments
 (0)