Skip to content

Commit a34697b

Browse files
authored
Merge pull request #7850 from eeckstein/demangle-swiftcc
demangler: swiftcc check and support of _S
2 parents c9dad65 + f8f172a commit a34697b

File tree

7 files changed

+97
-27
lines changed

7 files changed

+97
-27
lines changed

include/swift/Basic/Demangle.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,13 @@ class Context {
289289
/// or ObjC-as-swift thunks.
290290
bool isThunkSymbol(llvm::StringRef MangledName);
291291

292+
/// Returns true if the \p mangledName refers to a function which conforms to
293+
/// the Swift calling convention.
294+
///
295+
/// The return value is unspecified if the \p MangledName does not refer to a
296+
/// function symbol.
297+
bool hasSwiftCallingConvention(llvm::StringRef MangledName);
298+
292299
/// Deallocates all nodes.
293300
///
294301
/// The memory which is used for nodes is not freed but recycled for the next

include/swift/SwiftDemangle/SwiftDemangle.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
5353
char *OutputBuffer,
5454
size_t Length);
5555

56+
/// \brief Demangles a Swift function name and returns true if the function
57+
/// conforms to the Swift calling convention.
58+
///
59+
/// \returns true if the function conforms to the Swift calling convention.
60+
/// The return value is unspecified if the \p MangledName does not refer to a
61+
/// function symbol.
62+
int swift_demangle_hasSwiftCallingConvention(const char *MangledName);
63+
5664
#ifdef __cplusplus
5765
} // extern "C"
5866
#endif

lib/Basic/Demangle.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2331,7 +2331,9 @@ class OldDemangler {
23312331
bool
23322332
swift::Demangle::isSwiftSymbol(const char *mangledName) {
23332333
// The old mangling.
2334-
if (mangledName[0] == '_' && mangledName[1] == 'T')
2334+
if (mangledName[0] == '_'
2335+
// Also accept the future mangling prefix.
2336+
&& (mangledName[1] == 'T' || mangledName[1] == 'S'))
23352337
return true;
23362338

23372339
// The new mangling.

lib/Basic/Demangler.cpp

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ void Context::clear() {
137137

138138
NodePointer Context::demangleSymbolAsNode(llvm::StringRef MangledName) {
139139
#ifndef NO_NEW_DEMANGLING
140-
if (MangledName.startswith(MANGLING_PREFIX_STR)) {
140+
if (MangledName.startswith(MANGLING_PREFIX_STR)
141+
// Also accept the future mangling prefix.
142+
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
143+
|| MangledName.startswith("_S")) {
141144
return D->demangleSymbol(MangledName);
142145
}
143146
#endif
@@ -171,7 +174,10 @@ std::string Context::demangleTypeAsString(llvm::StringRef MangledName,
171174
}
172175

173176
bool Context::isThunkSymbol(llvm::StringRef MangledName) {
174-
if (MangledName.startswith(MANGLING_PREFIX_STR)) {
177+
if (MangledName.startswith(MANGLING_PREFIX_STR)
178+
// Also accept the future mangling prefix.
179+
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
180+
|| MangledName.startswith("_S")) {
175181
// First do a quick check
176182
if (MangledName.endswith("TA") || // partial application forwarder
177183
MangledName.endswith("Ta") || // ObjC partial application forwarder
@@ -208,7 +214,31 @@ bool Context::isThunkSymbol(llvm::StringRef MangledName) {
208214
}
209215
return false;
210216
}
211-
217+
218+
bool Context::hasSwiftCallingConvention(llvm::StringRef MangledName) {
219+
Node *Global = demangleSymbolAsNode(MangledName);
220+
if (!Global || Global->getKind() != Node::Kind::Global ||
221+
Global->getNumChildren() == 0)
222+
return false;
223+
224+
Node *TopLevel = Global->getFirstChild();
225+
switch (TopLevel->getKind()) {
226+
// Functions, which don't have the swift calling conventions:
227+
case Node::Kind::TypeMetadataAccessFunction:
228+
case Node::Kind::ValueWitness:
229+
case Node::Kind::ProtocolWitnessTableAccessor:
230+
case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
231+
case Node::Kind::LazyProtocolWitnessTableAccessor:
232+
case Node::Kind::AssociatedTypeMetadataAccessor:
233+
case Node::Kind::AssociatedTypeWitnessTableAccessor:
234+
case Node::Kind::ObjCAttribute:
235+
return false;
236+
default:
237+
break;
238+
}
239+
return true;
240+
}
241+
212242
NodePointer Context::createNode(Node::Kind K) {
213243
return D->createNode(K);
214244
}
@@ -317,7 +347,10 @@ void Demangler::init(StringRef MangledName) {
317347
NodePointer Demangler::demangleSymbol(StringRef MangledName) {
318348
init(MangledName);
319349

320-
if (!nextIf(MANGLING_PREFIX_STR))
350+
if (!nextIf(MANGLING_PREFIX_STR)
351+
// Also accept the future mangling prefix.
352+
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
353+
&& !nextIf("_S"))
321354
return nullptr;
322355

323356
NodePointer topLevel = createNode(Node::Kind::Global);

lib/SwiftDemangle/SwiftDemangle.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
5454
Length, Opts);
5555
}
5656

57+
int swift_demangle_hasSwiftCallingConvention(const char *MangledName) {
58+
swift::Demangle::Context DCtx;
59+
if (DCtx.hasSwiftCallingConvention(llvm::StringRef(MangledName)))
60+
return 1;
61+
return 0;
62+
}
63+
5764
size_t fnd_get_demangled_name(const char *MangledName, char *OutputBuffer,
5865
size_t Length) {
5966
return swift_demangle_getDemangledName(MangledName, OutputBuffer, Length);

test/Demangle/Inputs/manglings.txt

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ _TF3foolp3barSi ---> foo.bar.nativePinningAddressor : Swift.Int
7777
_TF3foog3barSi ---> foo.bar.getter : Swift.Int
7878
_TF3foos3barSi ---> foo.bar.setter : Swift.Int
7979
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
80-
_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
80+
_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
8181
_TTOFSC3fooFTSdSd_Sd ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
82-
_T03foo3barC3basyAA3zimCAE_tFTo ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
82+
_T03foo3barC3basyAA3zimCAE_tFTo ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
8383
_T0SC3fooSdSd_SdtFTO ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
84+
_S3foo3barC3basyAA3zimCAE_tFTo ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
85+
_SSC3fooSdSd_SdtFTO ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
8486
_TTDFC3foo3bar3basfT3zimCS_3zim_T_ ---> dynamic foo.bar.bas (zim : foo.zim) -> ()
8587
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
8688
_TF3foooi1pFTCS_3barVS_3bas_OS_3zim ---> foo.+ infix (foo.bar, foo.bas) -> foo.zim
@@ -94,31 +96,31 @@ _TMnC3foo3bar ---> nominal type descriptor for foo.bar
9496
_TMmC3foo3bar ---> metaclass for foo.bar
9597
_TMC3foo3bar ---> type metadata for foo.bar
9698
_TMfC3foo3bar ---> full type metadata for foo.bar
97-
_TwalC3foo3bar ---> allocateBuffer value witness for foo.bar
98-
_TwcaC3foo3bar ---> assignWithCopy value witness for foo.bar
99-
_TwtaC3foo3bar ---> assignWithTake value witness for foo.bar
100-
_TwdeC3foo3bar ---> deallocateBuffer value witness for foo.bar
101-
_TwxxC3foo3bar ---> destroy value witness for foo.bar
102-
_TwXXC3foo3bar ---> destroyBuffer value witness for foo.bar
103-
_TwCPC3foo3bar ---> initializeBufferWithCopyOfBuffer value witness for foo.bar
104-
_TwCpC3foo3bar ---> initializeBufferWithCopy value witness for foo.bar
105-
_TwcpC3foo3bar ---> initializeWithCopy value witness for foo.bar
106-
_TwTKC3foo3bar ---> initializeBufferWithTakeOfBuffer value witness for foo.bar
107-
_TwTkC3foo3bar ---> initializeBufferWithTake value witness for foo.bar
108-
_TwtkC3foo3bar ---> initializeWithTake value witness for foo.bar
109-
_TwprC3foo3bar ---> projectBuffer value witness for foo.bar
99+
_TwalC3foo3bar ---> {C} allocateBuffer value witness for foo.bar
100+
_TwcaC3foo3bar ---> {C} assignWithCopy value witness for foo.bar
101+
_TwtaC3foo3bar ---> {C} assignWithTake value witness for foo.bar
102+
_TwdeC3foo3bar ---> {C} deallocateBuffer value witness for foo.bar
103+
_TwxxC3foo3bar ---> {C} destroy value witness for foo.bar
104+
_TwXXC3foo3bar ---> {C} destroyBuffer value witness for foo.bar
105+
_TwCPC3foo3bar ---> {C} initializeBufferWithCopyOfBuffer value witness for foo.bar
106+
_TwCpC3foo3bar ---> {C} initializeBufferWithCopy value witness for foo.bar
107+
_TwcpC3foo3bar ---> {C} initializeWithCopy value witness for foo.bar
108+
_TwTKC3foo3bar ---> {C} initializeBufferWithTakeOfBuffer value witness for foo.bar
109+
_TwTkC3foo3bar ---> {C} initializeBufferWithTake value witness for foo.bar
110+
_TwtkC3foo3bar ---> {C} initializeWithTake value witness for foo.bar
111+
_TwprC3foo3bar ---> {C} projectBuffer value witness for foo.bar
110112
_TWVC3foo3bar ---> value witness table for foo.bar
111113
_TWoFC3foo3bar3basFSiSi ---> witness table offset for foo.bar.bas (Swift.Int) -> Swift.Int
112114
_TWvdvC3foo3bar3basSi ---> direct field offset for foo.bar.bas : Swift.Int
113115
_TWvivC3foo3bar3basSi ---> indirect field offset for foo.bar.bas : Swift.Int
114116
_TWPC3foo3barS_8barrables ---> protocol witness table for foo.bar : foo.barrable in Swift
115-
_TWaC3foo3barS_8barrableS_ ---> protocol witness table accessor for foo.bar : foo.barrable in foo
116-
_TWlC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
117+
_TWaC3foo3barS_8barrableS_ ---> {C} protocol witness table accessor for foo.bar : foo.barrable in foo
118+
_TWlC3foo3barS0_S_8barrableS_ ---> {C} lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
117119
_TWLC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table cache variable for type foo.bar and conformance foo.bar : foo.barrable in foo
118120
_TWGC3foo3barS_8barrableS_ ---> generic protocol witness table for foo.bar : foo.barrable in foo
119-
_TWIC3foo3barS_8barrableS_ ---> instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
120-
_TWtC3foo3barS_8barrableS_4fred ---> associated type metadata accessor for fred in foo.bar : foo.barrable in foo
121-
_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
121+
_TWIC3foo3barS_8barrableS_ ---> {C} instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
122+
_TWtC3foo3barS_8barrableS_4fred ---> {C} associated type metadata accessor for fred in foo.bar : foo.barrable in foo
123+
_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> {C} associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
122124
_TFSCg5greenVSC5Color ---> __C.green.getter : __C.Color
123125
_TIF1t1fFT1iSi1sSS_T_A_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 0)
124126
_TIF1t1fFT1iSi1sSS_T_A0_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 1)

tools/swift-demangle/swift-demangle.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,15 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
9999
// mangling and demangling tests.
100100
remangled = name;
101101
} else {
102+
// Also accept the future mangling prefix.
103+
// TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
102104
remangled = swift::Demangle::mangleNode(pointer,
103-
/*NewMangling*/ name.startswith(MANGLING_PREFIX_STR));
105+
/*NewMangling*/ name.startswith(MANGLING_PREFIX_STR)
106+
|| name.startswith("_S"));
107+
if (name.startswith("_S")) {
108+
assert(remangled.find(MANGLING_PREFIX_STR) == 0);
109+
remangled = "_S" + remangled.substr(3);
110+
}
104111
if (name != remangled) {
105112
llvm::errs() << "\nError: re-mangled name \n " << remangled
106113
<< "\ndoes not match original name\n " << name << '\n';
@@ -132,6 +139,8 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
132139
Classifications += 'N';
133140
if (DCtx.isThunkSymbol(name))
134141
Classifications += 'T';
142+
if (pointer && !DCtx.hasSwiftCallingConvention(name))
143+
Classifications += 'C';
135144
if (!Classifications.empty())
136145
llvm::outs() << '{' << Classifications << "} ";
137146
}
@@ -142,7 +151,9 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
142151

143152
static int demangleSTDIN(const swift::Demangle::DemangleOptions &options) {
144153
// This doesn't handle Unicode symbols, but maybe that's okay.
145-
llvm::Regex maybeSymbol("(_T|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$]+");
154+
// Also accept the future mangling prefix.
155+
// TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
156+
llvm::Regex maybeSymbol("(_T|_S|" MANGLING_PREFIX_STR ")[_a-zA-Z0-9$]+");
146157

147158
swift::Demangle::Context DCtx;
148159
for (std::string mangled; std::getline(std::cin, mangled);) {

0 commit comments

Comments
 (0)