Skip to content

Commit 706f4c8

Browse files
committed
Demangler library: add a function swift_demangle_getModuleName to get the module name of a mangled symbol.
rdar://problem/47560963
1 parent de86e4f commit 706f4c8

File tree

6 files changed

+116
-19
lines changed

6 files changed

+116
-19
lines changed

include/swift/Demangling/Demangle.h

+16
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ class Context {
379379
/// function symbol.
380380
bool hasSwiftCallingConvention(llvm::StringRef MangledName);
381381

382+
/// Demangle the given symbol and return the module name of the symbol.
383+
///
384+
/// \param MangledName The mangled symbol string, which start a mangling
385+
/// prefix: _T, _T0, $S, _$S.
386+
///
387+
/// \returns The module name.
388+
std::string getModuleName(llvm::StringRef mangledName);
389+
382390
/// Deallocates all nodes.
383391
///
384392
/// The memory which is used for nodes is not freed but recycled for the next
@@ -578,6 +586,14 @@ bool isSpecialized(Node *node);
578586
NodePointer getUnspecialized(Node *node, NodeFactory &Factory);
579587
std::string archetypeName(Node::IndexType index, Node::IndexType depth);
580588

589+
/// Returns true if the node \p kind refers to a context node, e.g. a nominal
590+
/// type or a function.
591+
bool isContext(Node::Kind kind);
592+
593+
/// Returns true if the node \p kind refers to a node which is placed before a
594+
/// function node, e.g. a specialization attribute.
595+
bool isFunctionAttr(Node::Kind kind);
596+
581597
/// Form a StringRef around the mangled name starting at base, if the name may
582598
/// contain symbolic references.
583599
llvm::StringRef makeSymbolicMangledNameStringRef(const char *base);

include/swift/SwiftDemangle/SwiftDemangle.h

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
5757
char *OutputBuffer,
5858
size_t Length);
5959

60+
/// Demangle a Swift symbol and return the module name of the mangled entity.
61+
///
62+
/// \returns the length of the demangled module name (even if greater than the
63+
/// size of the output buffer) or 0 if the input is not a Swift-mangled name
64+
/// (in which cases \p OutputBuffer is left untouched).
65+
SWIFT_DEMANGLE_LINKAGE
66+
size_t swift_demangle_getModuleName(const char *MangledName,
67+
char *OutputBuffer,
68+
size_t Length);
69+
6070
/// Demangles a Swift function name and returns true if the function
6171
/// conforms to the Swift calling convention.
6272
///

lib/Demangling/Context.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,43 @@ bool Context::hasSwiftCallingConvention(llvm::StringRef MangledName) {
171171
return true;
172172
}
173173

174+
std::string Context::getModuleName(llvm::StringRef mangledName) {
175+
NodePointer node = demangleSymbolAsNode(mangledName);
176+
while (node) {
177+
switch (node->getKind()) {
178+
case Demangle::Node::Kind::Module:
179+
return node->getText().str();
180+
case Demangle::Node::Kind::TypeMangling:
181+
case Demangle::Node::Kind::Type:
182+
node = node->getFirstChild();
183+
break;
184+
case Demangle::Node::Kind::Global: {
185+
NodePointer newNode = nullptr;
186+
for (NodePointer child : *node) {
187+
if (!isFunctionAttr(child->getKind())) {
188+
newNode = child;
189+
break;
190+
}
191+
}
192+
node = newNode;
193+
break;
194+
}
195+
default:
196+
if (isSpecialized(node)) {
197+
node = getUnspecialized(node, *D);
198+
break;
199+
}
200+
if (isContext(node->getKind())) {
201+
node = node->getFirstChild();
202+
break;
203+
}
204+
return std::string();
205+
}
206+
}
207+
return std::string();
208+
}
209+
210+
174211
//////////////////////////////////
175212
// Public utility functions //
176213
//////////////////////////////////

lib/Demangling/Demangler.cpp

+19-19
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,6 @@ static bool isDeclName(Node::Kind kind) {
4747
}
4848
}
4949

50-
static bool isContext(Node::Kind kind) {
51-
switch (kind) {
52-
#define NODE(ID)
53-
#define CONTEXT_NODE(ID) \
54-
case Node::Kind::ID:
55-
#include "swift/Demangling/DemangleNodes.def"
56-
return true;
57-
default:
58-
return false;
59-
}
60-
}
61-
6250
static bool isAnyGeneric(Node::Kind kind) {
6351
switch (kind) {
6452
case Node::Kind::Structure:
@@ -93,7 +81,25 @@ static bool isRequirement(Node::Kind kind) {
9381
}
9482
}
9583

96-
static bool isFunctionAttr(Node::Kind kind) {
84+
} // anonymous namespace
85+
86+
//////////////////////////////////
87+
// Public utility functions //
88+
//////////////////////////////////
89+
90+
bool swift::Demangle::isContext(Node::Kind kind) {
91+
switch (kind) {
92+
#define NODE(ID)
93+
#define CONTEXT_NODE(ID) \
94+
case Node::Kind::ID:
95+
#include "swift/Demangling/DemangleNodes.def"
96+
return true;
97+
default:
98+
return false;
99+
}
100+
}
101+
102+
bool swift::Demangle::isFunctionAttr(Node::Kind kind) {
97103
switch (kind) {
98104
case Node::Kind::FunctionSignatureSpecialization:
99105
case Node::Kind::GenericSpecialization:
@@ -120,12 +126,6 @@ static bool isFunctionAttr(Node::Kind kind) {
120126
}
121127
}
122128

123-
} // anonymous namespace
124-
125-
//////////////////////////////////
126-
// Public utility functions //
127-
//////////////////////////////////
128-
129129
llvm::StringRef
130130
swift::Demangle::makeSymbolicMangledNameStringRef(const char *base) {
131131
if (!base)

lib/SwiftDemangle/SwiftDemangle.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
5858
Length, Opts);
5959
}
6060

61+
size_t swift_demangle_getModuleName(const char *MangledName,
62+
char *OutputBuffer,
63+
size_t Length) {
64+
65+
swift::Demangle::Context DCtx;
66+
std::string Result = DCtx.getModuleName(llvm::StringRef(MangledName));
67+
68+
// Copy the result to an output buffer and ensure '\0' termination.
69+
if (OutputBuffer && Length > 0) {
70+
auto Dest = strncpy(OutputBuffer, Result.c_str(), Length);
71+
Dest[Length - 1] = '\0';
72+
}
73+
return Result.length();
74+
}
75+
76+
6177
int swift_demangle_hasSwiftCallingConvention(const char *MangledName) {
6278
swift::Demangle::Context DCtx;
6379
if (DCtx.hasSwiftCallingConvention(llvm::StringRef(MangledName)))

unittests/SwiftDemangle/DemangleTest.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,21 @@ TEST(FunctionNameDemangleTests, IgnoresNonMangledInputs) {
8787
EXPECT_STREQ("0123456789abcdef", OutputBuffer);
8888
}
8989

90+
TEST(FunctionNameDemangleTests, ModuleName) {
91+
const char *Sym1 = "_TtCs5Class";
92+
const char *ModuleName1 = "Swift";
93+
const char *Sym2 = "_TtCC3Mod7ExampleP33_211017DA67536A354F5F5EB94C7AC12E2Pv";
94+
const char *ModuleName2 = "Mod";
95+
char OutputBuffer[128];
96+
97+
size_t Result = swift_demangle_getModuleName(Sym1, OutputBuffer,
98+
sizeof(OutputBuffer));
99+
EXPECT_STREQ(ModuleName1, OutputBuffer);
100+
EXPECT_EQ(Result, strlen(ModuleName1));
101+
102+
Result = swift_demangle_getModuleName(Sym2, OutputBuffer,
103+
sizeof(OutputBuffer));
104+
EXPECT_STREQ(ModuleName2, OutputBuffer);
105+
EXPECT_EQ(Result, strlen(ModuleName2));
106+
}
107+

0 commit comments

Comments
 (0)