Skip to content

demangler: swiftcc check and support of _S #7850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/swift/Basic/Demangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,13 @@ class Context {
/// or ObjC-as-swift thunks.
bool isThunkSymbol(llvm::StringRef MangledName);

/// Returns true if the \p mangledName refers to a function which conforms to
/// the Swift calling convention.
///
/// The return value is unspecified if the \p MangledName does not refer to a
/// function symbol.
bool hasSwiftCallingConvention(llvm::StringRef MangledName);

/// Deallocates all nodes.
///
/// The memory which is used for nodes is not freed but recycled for the next
Expand Down
8 changes: 8 additions & 0 deletions include/swift/SwiftDemangle/SwiftDemangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
char *OutputBuffer,
size_t Length);

/// \brief Demangles a Swift function name and returns true if the function
/// conforms to the Swift calling convention.
///
/// \returns true if the function conforms to the Swift calling convention.
/// The return value is unspecified if the \p MangledName does not refer to a
/// function symbol.
int swift_demangle_hasSwiftCallingConvention(const char *MangledName);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
4 changes: 3 additions & 1 deletion lib/Basic/Demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2331,7 +2331,9 @@ class OldDemangler {
bool
swift::Demangle::isSwiftSymbol(const char *mangledName) {
// The old mangling.
if (mangledName[0] == '_' && mangledName[1] == 'T')
if (mangledName[0] == '_'
// Also accept the future mangling prefix.
&& (mangledName[1] == 'T' || mangledName[1] == 'S'))
return true;

// The new mangling.
Expand Down
41 changes: 37 additions & 4 deletions lib/Basic/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ void Context::clear() {

NodePointer Context::demangleSymbolAsNode(llvm::StringRef MangledName) {
#ifndef NO_NEW_DEMANGLING
if (MangledName.startswith(MANGLING_PREFIX_STR)) {
if (MangledName.startswith(MANGLING_PREFIX_STR)
// Also accept the future mangling prefix.
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
|| MangledName.startswith("_S")) {
return D->demangleSymbol(MangledName);
}
#endif
Expand Down Expand Up @@ -171,7 +174,10 @@ std::string Context::demangleTypeAsString(llvm::StringRef MangledName,
}

bool Context::isThunkSymbol(llvm::StringRef MangledName) {
if (MangledName.startswith(MANGLING_PREFIX_STR)) {
if (MangledName.startswith(MANGLING_PREFIX_STR)
// Also accept the future mangling prefix.
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
|| MangledName.startswith("_S")) {
// First do a quick check
if (MangledName.endswith("TA") || // partial application forwarder
MangledName.endswith("Ta") || // ObjC partial application forwarder
Expand Down Expand Up @@ -208,7 +214,31 @@ bool Context::isThunkSymbol(llvm::StringRef MangledName) {
}
return false;
}


bool Context::hasSwiftCallingConvention(llvm::StringRef MangledName) {
Node *Global = demangleSymbolAsNode(MangledName);
if (!Global || Global->getKind() != Node::Kind::Global ||
Global->getNumChildren() == 0)
return false;

Node *TopLevel = Global->getFirstChild();
switch (TopLevel->getKind()) {
// Functions, which don't have the swift calling conventions:
case Node::Kind::TypeMetadataAccessFunction:
case Node::Kind::ValueWitness:
case Node::Kind::ProtocolWitnessTableAccessor:
case Node::Kind::GenericProtocolWitnessTableInstantiationFunction:
case Node::Kind::LazyProtocolWitnessTableAccessor:
case Node::Kind::AssociatedTypeMetadataAccessor:
case Node::Kind::AssociatedTypeWitnessTableAccessor:
case Node::Kind::ObjCAttribute:
return false;
default:
break;
}
return true;
}

NodePointer Context::createNode(Node::Kind K) {
return D->createNode(K);
}
Expand Down Expand Up @@ -317,7 +347,10 @@ void Demangler::init(StringRef MangledName) {
NodePointer Demangler::demangleSymbol(StringRef MangledName) {
init(MangledName);

if (!nextIf(MANGLING_PREFIX_STR))
if (!nextIf(MANGLING_PREFIX_STR)
// Also accept the future mangling prefix.
// TODO: remove this line as soon as MANGLING_PREFIX_STR gets "_S".
&& !nextIf("_S"))
return nullptr;

NodePointer topLevel = createNode(Node::Kind::Global);
Expand Down
7 changes: 7 additions & 0 deletions lib/SwiftDemangle/SwiftDemangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ size_t swift_demangle_getSimplifiedDemangledName(const char *MangledName,
Length, Opts);
}

int swift_demangle_hasSwiftCallingConvention(const char *MangledName) {
swift::Demangle::Context DCtx;
if (DCtx.hasSwiftCallingConvention(llvm::StringRef(MangledName)))
return 1;
return 0;
}

size_t fnd_get_demangled_name(const char *MangledName, char *OutputBuffer,
size_t Length) {
return swift_demangle_getDemangledName(MangledName, OutputBuffer, Length);
Expand Down
42 changes: 22 additions & 20 deletions test/Demangle/Inputs/manglings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,12 @@ _TF3foolp3barSi ---> foo.bar.nativePinningAddressor : Swift.Int
_TF3foog3barSi ---> foo.bar.getter : Swift.Int
_TF3foos3barSi ---> foo.bar.setter : Swift.Int
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
_TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
_TTOFSC3fooFTSdSd_Sd ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
_T03foo3barC3basyAA3zimCAE_tFTo ---> {T} @objc foo.bar.bas (zim : foo.zim) -> ()
_T03foo3barC3basyAA3zimCAE_tFTo ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
_T0SC3fooSdSd_SdtFTO ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
_S3foo3barC3basyAA3zimCAE_tFTo ---> {TC} @objc foo.bar.bas (zim : foo.zim) -> ()
_SSC3fooSdSd_SdtFTO ---> {T} @nonobjc __C.foo (Swift.Double, Swift.Double) -> Swift.Double
_TTDFC3foo3bar3basfT3zimCS_3zim_T_ ---> dynamic foo.bar.bas (zim : foo.zim) -> ()
_TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas (zim : foo.zim) -> ()
_TF3foooi1pFTCS_3barVS_3bas_OS_3zim ---> foo.+ infix (foo.bar, foo.bas) -> foo.zim
Expand All @@ -94,31 +96,31 @@ _TMnC3foo3bar ---> nominal type descriptor for foo.bar
_TMmC3foo3bar ---> metaclass for foo.bar
_TMC3foo3bar ---> type metadata for foo.bar
_TMfC3foo3bar ---> full type metadata for foo.bar
_TwalC3foo3bar ---> allocateBuffer value witness for foo.bar
_TwcaC3foo3bar ---> assignWithCopy value witness for foo.bar
_TwtaC3foo3bar ---> assignWithTake value witness for foo.bar
_TwdeC3foo3bar ---> deallocateBuffer value witness for foo.bar
_TwxxC3foo3bar ---> destroy value witness for foo.bar
_TwXXC3foo3bar ---> destroyBuffer value witness for foo.bar
_TwCPC3foo3bar ---> initializeBufferWithCopyOfBuffer value witness for foo.bar
_TwCpC3foo3bar ---> initializeBufferWithCopy value witness for foo.bar
_TwcpC3foo3bar ---> initializeWithCopy value witness for foo.bar
_TwTKC3foo3bar ---> initializeBufferWithTakeOfBuffer value witness for foo.bar
_TwTkC3foo3bar ---> initializeBufferWithTake value witness for foo.bar
_TwtkC3foo3bar ---> initializeWithTake value witness for foo.bar
_TwprC3foo3bar ---> projectBuffer value witness for foo.bar
_TwalC3foo3bar ---> {C} allocateBuffer value witness for foo.bar
_TwcaC3foo3bar ---> {C} assignWithCopy value witness for foo.bar
_TwtaC3foo3bar ---> {C} assignWithTake value witness for foo.bar
_TwdeC3foo3bar ---> {C} deallocateBuffer value witness for foo.bar
_TwxxC3foo3bar ---> {C} destroy value witness for foo.bar
_TwXXC3foo3bar ---> {C} destroyBuffer value witness for foo.bar
_TwCPC3foo3bar ---> {C} initializeBufferWithCopyOfBuffer value witness for foo.bar
_TwCpC3foo3bar ---> {C} initializeBufferWithCopy value witness for foo.bar
_TwcpC3foo3bar ---> {C} initializeWithCopy value witness for foo.bar
_TwTKC3foo3bar ---> {C} initializeBufferWithTakeOfBuffer value witness for foo.bar
_TwTkC3foo3bar ---> {C} initializeBufferWithTake value witness for foo.bar
_TwtkC3foo3bar ---> {C} initializeWithTake value witness for foo.bar
_TwprC3foo3bar ---> {C} projectBuffer value witness for foo.bar
_TWVC3foo3bar ---> value witness table for foo.bar
_TWoFC3foo3bar3basFSiSi ---> witness table offset for foo.bar.bas (Swift.Int) -> Swift.Int
_TWvdvC3foo3bar3basSi ---> direct field offset for foo.bar.bas : Swift.Int
_TWvivC3foo3bar3basSi ---> indirect field offset for foo.bar.bas : Swift.Int
_TWPC3foo3barS_8barrables ---> protocol witness table for foo.bar : foo.barrable in Swift
_TWaC3foo3barS_8barrableS_ ---> protocol witness table accessor for foo.bar : foo.barrable in foo
_TWlC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
_TWaC3foo3barS_8barrableS_ ---> {C} protocol witness table accessor for foo.bar : foo.barrable in foo
_TWlC3foo3barS0_S_8barrableS_ ---> {C} lazy protocol witness table accessor for type foo.bar and conformance foo.bar : foo.barrable in foo
_TWLC3foo3barS0_S_8barrableS_ ---> lazy protocol witness table cache variable for type foo.bar and conformance foo.bar : foo.barrable in foo
_TWGC3foo3barS_8barrableS_ ---> generic protocol witness table for foo.bar : foo.barrable in foo
_TWIC3foo3barS_8barrableS_ ---> instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
_TWtC3foo3barS_8barrableS_4fred ---> associated type metadata accessor for fred in foo.bar : foo.barrable in foo
_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
_TWIC3foo3barS_8barrableS_ ---> {C} instantiation function for generic protocol witness table for foo.bar : foo.barrable in foo
_TWtC3foo3barS_8barrableS_4fred ---> {C} associated type metadata accessor for fred in foo.bar : foo.barrable in foo
_TWTC3foo3barS_8barrableS_4fredS_6thomas ---> {C} associated type witness table accessor for fred : foo.thomas in foo.bar : foo.barrable in foo
_TFSCg5greenVSC5Color ---> __C.green.getter : __C.Color
_TIF1t1fFT1iSi1sSS_T_A_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 0)
_TIF1t1fFT1iSi1sSS_T_A0_ ---> t.(f (i : Swift.Int, s : Swift.String) -> ()).(default argument 1)
Expand Down
15 changes: 13 additions & 2 deletions tools/swift-demangle/swift-demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,15 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
// mangling and demangling tests.
remangled = name;
} else {
// Also accept the future mangling prefix.
// TODO: remove the "_S" as soon as MANGLING_PREFIX_STR gets "_S".
remangled = swift::Demangle::mangleNode(pointer,
/*NewMangling*/ name.startswith(MANGLING_PREFIX_STR));
/*NewMangling*/ name.startswith(MANGLING_PREFIX_STR)
|| name.startswith("_S"));
if (name.startswith("_S")) {
assert(remangled.find(MANGLING_PREFIX_STR) == 0);
remangled = "_S" + remangled.substr(3);
}
if (name != remangled) {
llvm::errs() << "\nError: re-mangled name \n " << remangled
<< "\ndoes not match original name\n " << name << '\n';
Expand Down Expand Up @@ -132,6 +139,8 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,
Classifications += 'N';
if (DCtx.isThunkSymbol(name))
Classifications += 'T';
if (pointer && !DCtx.hasSwiftCallingConvention(name))
Classifications += 'C';
if (!Classifications.empty())
llvm::outs() << '{' << Classifications << "} ";
}
Expand All @@ -142,7 +151,9 @@ static void demangle(llvm::raw_ostream &os, llvm::StringRef name,

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

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