Skip to content

Commit 987d055

Browse files
[Mangler] Handle mangling for Clang types not derivable from Swift types.
1 parent be109b7 commit 987d055

File tree

16 files changed

+328
-55
lines changed

16 files changed

+328
-55
lines changed

docs/ABI/Mangling.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,15 +523,20 @@ Types
523523
FUNCTION-KIND ::= 'U' // uncurried function type (currently not used)
524524
FUNCTION-KIND ::= 'K' // @auto_closure function type (noescape)
525525
FUNCTION-KIND ::= 'B' // objc block function type
526-
FUNCTION-KIND ::= 'L' // objc block function type (escaping) (DWARF only; otherwise use 'B')
526+
FUNCTION-KIND ::= 'zB' C-TYPE // objc block type with non-canonical C type
527+
FUNCTION-KIND ::= 'L' // objc block function type with canonical C type (escaping) (DWARF only; otherwise use 'B' or 'zB' C-TYPE)
527528
FUNCTION-KIND ::= 'C' // C function pointer type
529+
FUNCTION-KIND ::= 'zC' C-TYPE // C function pointer type with with non-canonical C type
528530
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
529531
FUNCTION-KIND ::= 'E' // function type (noescape)
530532
FUNCTION-KIND ::= 'F' // @differentiable function type
531533
FUNCTION-KIND ::= 'G' // @differentiable function type (escaping)
532534
FUNCTION-KIND ::= 'H' // @differentiable(linear) function type
533535
FUNCTION-KIND ::= 'I' // @differentiable(linear) function type (escaping)
534536

537+
C-TYPE is mangled according to the Itanium ABI, and prefixed with the length.
538+
Non-ASCII identifiers are preserved as-is; we do not use Punycode.
539+
535540
function-signature ::= params-type params-type async? throws? // results and parameters
536541

537542
params-type ::= type 'z'? 'h'? // tuple in case of multiple parameters or a single parameter with a single tuple type
@@ -618,7 +623,9 @@ mangled in to disambiguate.
618623
CALLEE-CONVENTION ::= 't' // thin
619624

620625
FUNC-REPRESENTATION ::= 'B' // C block invocation function
626+
FUNC-REPRESENTATION ::= 'zB' C-TYPE // C block invocation function with non-canonical C type
621627
FUNC-REPRESENTATION ::= 'C' // C global function
628+
FUNC-REPRESENTATION ::= 'zC' C-TYPE // C global function with non-canonical C type
622629
FUNC-REPRESENTATION ::= 'M' // Swift method
623630
FUNC-REPRESENTATION ::= 'J' // ObjC method
624631
FUNC-REPRESENTATION ::= 'K' // closure

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,9 @@ class ASTMangler : public Mangler {
318318
const ValueDecl *forDecl = nullptr);
319319
void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false,
320320
const ValueDecl *forDecl = nullptr);
321+
void appendClangType(AnyFunctionType *fn);
322+
template <typename FnType>
323+
void appendClangType(FnType *fn, llvm::raw_svector_ostream &os);
321324

322325
void appendFunctionSignature(AnyFunctionType *fn,
323326
const ValueDecl *forDecl = nullptr);

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ NODE(BoundGenericTypeAlias)
4444
NODE(BoundGenericFunction)
4545
NODE(BuiltinTypeName)
4646
NODE(CFunctionPointer)
47+
NODE(ClangType)
4748
CONTEXT_NODE(Class)
4849
NODE(ClassMetadataBaseOffset)
4950
NODE(ConcreteProtocolConformance)
@@ -119,6 +120,8 @@ NODE(ImplEscaping)
119120
NODE(ImplConvention)
120121
NODE(ImplDifferentiability)
121122
NODE(ImplFunctionAttribute)
123+
NODE(ImplFunctionConvention)
124+
NODE(ImplFunctionConventionName)
122125
NODE(ImplFunctionType)
123126
NODE(ImplInvocationSubstitutions)
124127
CONTEXT_NODE(ImplicitClosure)

include/swift/Demangling/Demangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ class Demangler : public NodeFactory {
505505
NodePointer demangleAnyGenericType(Node::Kind kind);
506506
NodePointer demangleExtensionContext();
507507
NodePointer demanglePlainFunction();
508-
NodePointer popFunctionType(Node::Kind kind);
508+
NodePointer popFunctionType(Node::Kind kind, bool hasClangType = false);
509509
NodePointer popFunctionParams(Node::Kind kind);
510510
NodePointer popFunctionParamLabels(NodePointer FuncType);
511511
NodePointer popTuple();
@@ -522,6 +522,7 @@ class Demangler : public NodeFactory {
522522
NodePointer demangleImplResultConvention(Node::Kind ConvKind);
523523
NodePointer demangleImplDifferentiability();
524524
NodePointer demangleImplFunctionType();
525+
NodePointer demangleClangType();
525526
NodePointer demangleMetatype();
526527
NodePointer demanglePrivateContextDescriptor();
527528
NodePointer createArchetypeRef(int depth, int i);

include/swift/Demangling/TypeDecoder.h

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,12 @@ class TypeDecoder {
631631
}
632632

633633
unsigned firstChildIdx = 0;
634+
if (Node->getChild(firstChildIdx)->getKind() == NodeKind::ClangType) {
635+
// [TODO: synthesize-Clang-type-from-mangled-name] Use the first child
636+
// to create a ClangTypeInfo.
637+
++firstChildIdx;
638+
}
639+
634640
bool isThrow = false;
635641
if (Node->getChild(firstChildIdx)->getKind()
636642
== NodeKind::ThrowsAnnotation) {
@@ -695,18 +701,28 @@ class TypeDecoder {
695701
} else if (child->getText() == "@callee_guaranteed") {
696702
calleeConvention = ImplParameterConvention::Direct_Guaranteed;
697703
}
698-
} else if (child->getKind() == NodeKind::ImplFunctionAttribute) {
699-
if (!child->hasText())
700-
return MAKE_NODE_TYPE_ERROR0(child, "expected text");
701-
702-
StringRef text = child->getText();
703-
if (text == "@convention(c)") {
704+
} else if (child->getKind() == NodeKind::ImplFunctionConvention) {
705+
if (child->getNumChildren() == 0)
706+
return MAKE_NODE_TYPE_ERROR0(child, "expected grandchildren");
707+
if ((child->getFirstChild()->getKind() !=
708+
NodeKind::ImplFunctionConventionName) ||
709+
!child->getFirstChild()->hasText())
710+
return MAKE_NODE_TYPE_ERROR0(child, "expected convention name");
711+
712+
// [TODO: synthesize-Clang-type-from-mangled-name] If there are two
713+
// grand-children, the second is going to be the mangled Clang type.
714+
StringRef text = child->getFirstChild()->getText();
715+
if (text == "c") {
704716
flags =
705717
flags.withRepresentation(ImplFunctionRepresentation::CFunctionPointer);
706-
} else if (text == "@convention(block)") {
718+
} else if (text == "block") {
707719
flags =
708720
flags.withRepresentation(ImplFunctionRepresentation::Block);
709-
} else if (text == "@async") {
721+
}
722+
} else if (child->getKind() == NodeKind::ImplFunctionAttribute) {
723+
if (!child->hasText())
724+
return MAKE_NODE_TYPE_ERROR0(child, "expected text");
725+
if (child->getText() == "@async") {
710726
flags = flags.withAsync();
711727
}
712728
} else if (child->getKind() == NodeKind::ImplDifferentiable) {

lib/AST/ASTMangler.cpp

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,27 @@
3030
#include "swift/AST/ProtocolConformanceRef.h"
3131
#include "swift/AST/SILLayout.h"
3232
#include "swift/Basic/Defer.h"
33+
#include "swift/ClangImporter/ClangImporter.h"
34+
#include "swift/Demangling/Demangler.h"
3335
#include "swift/Demangling/ManglingMacros.h"
3436
#include "swift/Demangling/ManglingUtils.h"
35-
#include "swift/Demangling/Demangler.h"
3637
#include "swift/Strings.h"
3738
#include "clang/AST/ASTContext.h"
38-
#include "clang/Basic/CharInfo.h"
3939
#include "clang/AST/Attr.h"
4040
#include "clang/AST/Decl.h"
4141
#include "clang/AST/DeclObjC.h"
4242
#include "clang/AST/DeclTemplate.h"
4343
#include "clang/AST/Mangle.h"
44+
#include "clang/Basic/CharInfo.h"
4445
#include "llvm/ADT/DenseMap.h"
4546
#include "llvm/ADT/SmallString.h"
4647
#include "llvm/ADT/StringRef.h"
48+
#include "llvm/Support/CommandLine.h"
4749
#include "llvm/Support/ErrorHandling.h"
4850
#include "llvm/Support/SaveAndRestore.h"
4951
#include "llvm/Support/raw_ostream.h"
50-
#include "llvm/Support/CommandLine.h"
52+
53+
#include <memory>
5154

5255
using namespace swift;
5356
using namespace swift::Mangle;
@@ -1653,15 +1656,35 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn) {
16531656
OpArgs.push_back('t');
16541657
}
16551658

1659+
bool mangleClangType = fn->getASTContext().LangOpts.UseClangFunctionTypes &&
1660+
fn->hasNonDerivableClangType();
1661+
1662+
auto appendClangTypeToVec = [this, fn](auto &Vec) {
1663+
llvm::raw_svector_ostream OpArgsOS(Vec);
1664+
appendClangType(fn, OpArgsOS);
1665+
};
1666+
16561667
switch (fn->getRepresentation()) {
16571668
case SILFunctionTypeRepresentation::Thick:
16581669
case SILFunctionTypeRepresentation::Thin:
16591670
break;
16601671
case SILFunctionTypeRepresentation::Block:
1672+
if (!mangleClangType) {
1673+
OpArgs.push_back('B');
1674+
break;
1675+
}
1676+
OpArgs.push_back('z');
16611677
OpArgs.push_back('B');
1678+
appendClangTypeToVec(OpArgs);
16621679
break;
16631680
case SILFunctionTypeRepresentation::CFunctionPointer:
1681+
if (!mangleClangType) {
1682+
OpArgs.push_back('C');
1683+
break;
1684+
}
1685+
OpArgs.push_back('z');
16641686
OpArgs.push_back('C');
1687+
appendClangTypeToVec(OpArgs);
16651688
break;
16661689
case SILFunctionTypeRepresentation::ObjCMethod:
16671690
OpArgs.push_back('O');
@@ -2244,6 +2267,9 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn, bool isAutoClosure,
22442267

22452268
appendFunctionSignature(fn, forDecl);
22462269

2270+
bool mangleClangType = fn->getASTContext().LangOpts.UseClangFunctionTypes &&
2271+
fn->hasNonDerivableClangType();
2272+
22472273
// Note that we do not currently use thin representations in the AST
22482274
// for the types of function decls. This may need to change at some
22492275
// point, in which case the uncurry logic can probably migrate to that
@@ -2256,6 +2282,10 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn, bool isAutoClosure,
22562282
// changes to better support thin functions.
22572283
switch (fn->getRepresentation()) {
22582284
case AnyFunctionType::Representation::Block:
2285+
if (mangleClangType) {
2286+
appendOperator("XzB");
2287+
return appendClangType(fn);
2288+
}
22592289
// We distinguish escaping and non-escaping blocks, but only in the DWARF
22602290
// mangling, because the ABI is already set.
22612291
if (!fn->isNoEscape() && DWARFMangling)
@@ -2287,10 +2317,31 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn, bool isAutoClosure,
22872317
return appendOperator("c");
22882318

22892319
case AnyFunctionType::Representation::CFunctionPointer:
2320+
if (mangleClangType) {
2321+
appendOperator("XzC");
2322+
return appendClangType(fn);
2323+
}
22902324
return appendOperator("XC");
22912325
}
22922326
}
22932327

2328+
template <typename FnType>
2329+
void ASTMangler::appendClangType(FnType *fn, llvm::raw_svector_ostream &out) {
2330+
auto clangType = fn->getClangTypeInfo().getType();
2331+
SmallString<64> scratch;
2332+
llvm::raw_svector_ostream scratchOS(scratch);
2333+
clang::ASTContext &clangCtx =
2334+
fn->getASTContext().getClangModuleLoader()->getClangASTContext();
2335+
std::unique_ptr<clang::ItaniumMangleContext> mangler{
2336+
clang::ItaniumMangleContext::create(clangCtx, clangCtx.getDiagnostics())};
2337+
mangler->mangleTypeName(clang::QualType(clangType, 0), scratchOS);
2338+
out << scratchOS.str().size() << scratchOS.str();
2339+
}
2340+
2341+
void ASTMangler::appendClangType(AnyFunctionType *fn) {
2342+
appendClangType(fn, Buffer);
2343+
}
2344+
22942345
void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
22952346
const ValueDecl *forDecl) {
22962347
appendFunctionResultType(fn->getResult(), forDecl);

lib/Demangling/Demangler.cpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,8 +1228,13 @@ NodePointer Demangler::demanglePlainFunction() {
12281228
return createWithChildren(Node::Kind::Function, Ctx, Name, Type);
12291229
}
12301230

1231-
NodePointer Demangler::popFunctionType(Node::Kind kind) {
1231+
NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) {
12321232
NodePointer FuncType = createNode(kind);
1233+
NodePointer ClangType = nullptr;
1234+
if (hasClangType) {
1235+
ClangType = demangleClangType();
1236+
}
1237+
addChild(FuncType, ClangType);
12331238
addChild(FuncType, popNode(Node::Kind::ThrowsAnnotation));
12341239
addChild(FuncType, popNode(Node::Kind::AsyncAnnotation));
12351240

@@ -1748,6 +1753,16 @@ NodePointer Demangler::demangleImplDifferentiability() {
17481753
return createNode(Node::Kind::ImplDifferentiability, attr);
17491754
}
17501755

1756+
NodePointer Demangler::demangleClangType() {
1757+
int numChars = demangleNatural();
1758+
if (numChars <= 0 || Pos + numChars > Text.size())
1759+
return nullptr;
1760+
CharVector mangledClangType;
1761+
mangledClangType.append(StringRef(Text.data() + Pos, numChars), *this);
1762+
Pos = Pos + numChars;
1763+
return createNode(Node::Kind::ClangType, mangledClangType);
1764+
}
1765+
17511766
NodePointer Demangler::demangleImplFunctionType() {
17521767
NodePointer type = createNode(Node::Kind::ImplFunctionType);
17531768

@@ -1806,20 +1821,33 @@ NodePointer Demangler::demangleImplFunctionType() {
18061821
}
18071822
type->addChild(createNode(Node::Kind::ImplConvention, CAttr), *this);
18081823

1809-
const char *FAttr = nullptr;
1824+
const char *FConv = nullptr;
1825+
bool hasClangType = false;
18101826
switch (nextChar()) {
1811-
case 'B': FAttr = "@convention(block)"; break;
1812-
case 'C': FAttr = "@convention(c)"; break;
1813-
case 'M': FAttr = "@convention(method)"; break;
1814-
case 'O': FAttr = "@convention(objc_method)"; break;
1815-
case 'K': FAttr = "@convention(closure)"; break;
1816-
case 'W': FAttr = "@convention(witness_method)"; break;
1817-
default:
1818-
pushBack();
1819-
break;
1827+
case 'B': FConv = "block"; break;
1828+
case 'C': FConv = "c"; break;
1829+
case 'z': {
1830+
switch (nextChar()) {
1831+
case 'B': hasClangType = true; FConv = "block"; break;
1832+
case 'C': hasClangType = true; FConv = "c"; break;
1833+
default: pushBack(); pushBack(); break;
1834+
}
1835+
break;
1836+
}
1837+
case 'M': FConv = "method"; break;
1838+
case 'O': FConv = "objc_method"; break;
1839+
case 'K': FConv = "closure"; break;
1840+
case 'W': FConv = "witness_method"; break;
1841+
default: pushBack(); break;
1842+
}
1843+
if (FConv) {
1844+
auto FAttrNode = createNode(Node::Kind::ImplFunctionConvention);
1845+
FAttrNode->addChild(
1846+
createNode(Node::Kind::ImplFunctionConventionName, FConv), *this);
1847+
if (hasClangType)
1848+
FAttrNode->addChild(demangleClangType(), *this);
1849+
type->addChild(FAttrNode, *this);
18201850
}
1821-
if (FAttr)
1822-
type->addChild(createNode(Node::Kind::ImplFunctionAttribute, FAttr), *this);
18231851

18241852
const char *CoroAttr = nullptr;
18251853
if (nextIf('A'))
@@ -2863,6 +2891,15 @@ NodePointer Demangler::demangleSpecialType() {
28632891
return popFunctionType(Node::Kind::ObjCBlock);
28642892
case 'C':
28652893
return popFunctionType(Node::Kind::CFunctionPointer);
2894+
case 'z':
2895+
switch (auto cchar = nextChar()) {
2896+
case 'B':
2897+
return popFunctionType(Node::Kind::ObjCBlock, true);
2898+
case 'C':
2899+
return popFunctionType(Node::Kind::CFunctionPointer, true);
2900+
default:
2901+
return nullptr;
2902+
}
28662903
case 'F':
28672904
return popFunctionType(Node::Kind::DifferentiableFunctionType);
28682905
case 'G':

0 commit comments

Comments
 (0)