Skip to content

Commit b9f47ba

Browse files
committed
[lldb] Handle @_originallyDefinedIn
Types annotated with @_originallyDefinedIn don't live in the module listed in their mangled name. To account for this, the compiler emits a DW_TAG_imported_declaration for those types under the name of the swiftmodule these types can be found at. This patch implements the logic required to produce the mangled name that can be used in type reconstruction to successfully find these types. rdar://137146961
1 parent 66d0442 commit b9f47ba

File tree

7 files changed

+499
-10
lines changed

7 files changed

+499
-10
lines changed

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4720,6 +4720,16 @@ SwiftASTContext::ReconstructType(ConstString mangled_typename) {
47204720
.getPointer();
47214721
assert(!found_type || &found_type->getASTContext() == *ast_ctx);
47224722

4723+
// This type might have been been found in reflection and annotated with
4724+
// @_originallyDefinedIn. The compiler emits a typelias for these type
4725+
// pointing them back to the types with the real module name.
4726+
if (!found_type) {
4727+
auto adjusted =
4728+
GetTypeSystemSwiftTypeRef().AdjustTypeForOriginallyDefinedInModule(
4729+
mangled_typename);
4730+
found_type =
4731+
swift::Demangle::getTypeForMangling(**ast_ctx, adjusted).getPointer();
4732+
}
47234733
// Objective-C classes sometimes have private subclasses that are invisible
47244734
// to the Swift compiler because they are declared and defined in a .m file.
47254735
// If we can't reconstruct an ObjC type, walk up the type hierarchy until we

lldb/source/Plugins/TypeSystem/Swift/SwiftDemangle.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,23 @@ NodeAtPath(swift::Demangle::NodePointer root,
5959
return ChildAtPath(root, kind_path.drop_front());
6060
}
6161

62-
/// \return the child of the \p Type node.
63-
static swift::Demangle::NodePointer GetType(swift::Demangle::NodePointer n) {
62+
/// \return the child of the TypeMangling node.
63+
static swift::Demangle::NodePointer
64+
GetTypeMangling(swift::Demangle::NodePointer n) {
6465
using namespace swift::Demangle;
6566
if (!n || n->getKind() != Node::Kind::Global)
6667
return nullptr;
6768
n = n->getFirstChild();
6869
if (!n || n->getKind() != Node::Kind::TypeMangling || !n->hasChildren())
6970
return nullptr;
7071
n = n->getFirstChild();
72+
return n;
73+
}
74+
75+
/// \return the child of the \p Type node.
76+
static swift::Demangle::NodePointer GetType(swift::Demangle::NodePointer n) {
77+
using namespace swift::Demangle;
78+
n = GetTypeMangling(n);
7179
if (!n || n->getKind() != Node::Kind::Type || !n->hasChildren())
7280
return nullptr;
7381
n = n->getFirstChild();
@@ -80,6 +88,14 @@ GetDemangledType(swift::Demangle::Demangler &dem, llvm::StringRef name) {
8088
return GetType(dem.demangleSymbol(name));
8189
}
8290

91+
/// Demangle a mangled type name and return the child of the \p TypeMangling
92+
/// node.
93+
inline swift::Demangle::NodePointer
94+
GetDemangledTypeMangling(swift::Demangle::Demangler &dem,
95+
llvm::StringRef name) {
96+
return GetTypeMangling(dem.demangleSymbol(name));
97+
}
98+
8399
/// Wrap node in Global/TypeMangling/Type.
84100
static swift::Demangle::NodePointer
85101
mangleType(swift::Demangle::Demangler &dem,

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 232 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434
#include "lldb/Utility/RegularExpression.h"
3535
#include "lldb/Utility/Timer.h"
3636

37-
#include "swift/ClangImporter/ClangImporter.h"
3837
#include "swift/../../lib/ClangImporter/ClangAdapter.h"
38+
#include "swift/ClangImporter/ClangImporter.h"
39+
#include "swift/Demangling/Demangler.h"
3940
#include "swift/Frontend/Frontend.h"
4041

4142
#include "clang/APINotes/APINotesManager.h"
@@ -150,6 +151,234 @@ TypeSystemSwiftTypeRef::CanonicalizeSugar(swift::Demangle::Demangler &dem,
150151
});
151152
}
152153

154+
swift::Demangle::ManglingErrorOr<std::string>
155+
TypeSystemSwiftTypeRef::TransformModuleName(
156+
llvm::StringRef mangled_name,
157+
const llvm::StringMap<llvm::StringRef> &module_name_map) {
158+
swift::Demangle::Demangler dem;
159+
auto *node = dem.demangleSymbol(mangled_name);
160+
auto *adjusted_node = TypeSystemSwiftTypeRef::Transform(
161+
dem, node, [&](swift::Demangle::NodePointer node) {
162+
if (node->getKind() == Node::Kind::Module) {
163+
auto module_name = node->getText();
164+
if (module_name_map.contains(module_name)) {
165+
auto real_name = module_name_map.lookup(module_name);
166+
auto *adjusted_module_node =
167+
dem.createNodeWithAllocatedText(Node::Kind::Module, real_name);
168+
return adjusted_module_node;
169+
}
170+
}
171+
172+
return node;
173+
});
174+
175+
auto mangling = mangleNode(adjusted_node);
176+
return mangling;
177+
}
178+
179+
static NodePointer CloneNode(Demangler &dem, NodePointer node,
180+
bool set_children = true) {
181+
NodePointer clone;
182+
auto kind = node->getKind();
183+
if (node->hasText())
184+
clone = dem.createNodeWithAllocatedText(kind, node->getText());
185+
else if (node->hasIndex())
186+
clone = dem.createNode(kind, node->getIndex());
187+
else
188+
clone = dem.createNode(kind);
189+
if (set_children)
190+
for (NodePointer transformed_child : *node)
191+
clone->addChild(transformed_child, dem);
192+
return clone;
193+
}
194+
195+
NodePointer TypeSystemSwiftTypeRef::TransformModuleName(
196+
NodePointer node, Demangler &dem,
197+
std::function<NodePointer(NodePointer)> module_transformer) {
198+
assert(node->getKind() == Node::Kind::Type);
199+
if (node->getKind() != Node::Kind::Type) {
200+
LLDB_LOGF(GetLog(LLDBLog::Types),
201+
"[TransformModuleName] Unexpected node kind %hu",
202+
static_cast<uint16_t>(node->getKind()));
203+
return nullptr;
204+
}
205+
206+
bool failed = false;
207+
std::function<NodePointer(NodePointer)> recurse_to_module_node =
208+
[&](NodePointer node) -> NodePointer {
209+
if (failed)
210+
return nullptr;
211+
// If the node has children this is not the module node yet, so recursively
212+
// examine the first child.
213+
if (node->hasChildren()) {
214+
NodePointer transformed = recurse_to_module_node(node->getFirstChild());
215+
// Clone the node because demangle trees share subtrees if they're the
216+
// same, and we don't want to accidentally mutate some other part of the
217+
// tree.
218+
NodePointer clone = CloneNode(dem, node);
219+
clone->replaceChild(0, transformed);
220+
return clone;
221+
}
222+
if (node->getKind() == Node::Kind::Module)
223+
return module_transformer(node);
224+
failed = true;
225+
return nullptr;
226+
};
227+
228+
NodePointer transformed = recurse_to_module_node(node);
229+
if (failed)
230+
LLDB_LOGF(GetLog(LLDBLog::Types),
231+
"[TransformModuleName] Failed to transform node %hu",
232+
static_cast<uint16_t>(node->getKind()));
233+
234+
return transformed;
235+
}
236+
237+
NodePointer TypeSystemSwiftTypeRef::TransformBoundGenericTypes(
238+
swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node,
239+
std::function<swift::Demangle::NodePointer(swift::Demangle::NodePointer)>
240+
type_transformer) {
241+
if (node->getKind() != Node::Kind::Type || !node->hasChildren())
242+
return node;
243+
244+
NodePointer bound_generic_node = node->getFirstChild();
245+
if (bound_generic_node->getNumChildren() != 2)
246+
return node;
247+
248+
NodePointer type_list_node = nullptr;
249+
switch (bound_generic_node->getKind()) {
250+
case Node::Kind::BoundGenericClass:
251+
case Node::Kind::BoundGenericEnum:
252+
case Node::Kind::BoundGenericStructure:
253+
case Node::Kind::BoundGenericProtocol:
254+
case Node::Kind::BoundGenericOtherNominalType:
255+
case Node::Kind::BoundGenericTypeAlias:
256+
type_list_node = bound_generic_node->getChild(1);
257+
break;
258+
default:
259+
return node;
260+
}
261+
assert(type_list_node && "No type list node!");
262+
263+
// Transform the bound generic types by applying type_transformer to all the
264+
// children of the type_list.
265+
NodePointer transformed_type_list =
266+
CloneNode(dem, type_list_node, /*set_children=*/false);
267+
for (NodePointer child : *type_list_node)
268+
transformed_type_list->addChild(type_transformer(child), dem);
269+
270+
bound_generic_node = CloneNode(dem, bound_generic_node);
271+
bound_generic_node->replaceChild(1, transformed_type_list);
272+
node = CloneNode(dem, node);
273+
node->replaceChild(0, bound_generic_node);
274+
return node;
275+
}
276+
277+
std::string TypeSystemSwiftTypeRef::AdjustTypeForOriginallyDefinedInModule(
278+
llvm::StringRef mangled_typename) {
279+
if (mangled_typename.empty())
280+
return {};
281+
282+
swift::Demangle::Demangler dem;
283+
auto *type_node =
284+
swift_demangle::GetDemangledTypeMangling(dem, mangled_typename);
285+
assert(type_node);
286+
if (!type_node)
287+
return {};
288+
289+
bool did_transform = false;
290+
std::function<NodePointer(NodePointer)> transform_all_module_nodes =
291+
[&](NodePointer node) -> NodePointer {
292+
auto compiler_type = RemangleAsType(dem, node);
293+
if (!compiler_type) {
294+
LLDB_LOG(GetLog(LLDBLog::Types),
295+
"[AdjustTypeForOriginallyDefinedInModule] Unexpected mangling "
296+
"error when mangling adjusted node for type with mangled name "
297+
"{0}",
298+
mangled_typename);
299+
300+
return node;
301+
}
302+
303+
// If this type has an @_originallyDefinedIn attribute, the compiler will
304+
// emit a typealias whose name is prefixed by $ODI followed by the mangled
305+
// name.
306+
TargetSP target_sp(GetTargetWP().lock());
307+
if (!target_sp)
308+
return node;
309+
ModuleList &module_list = target_sp->GetImages();
310+
std::vector<ImportedDeclaration> decls;
311+
module_list.FindImportedDeclarations(GetModule(),
312+
compiler_type.GetMangledTypeName(),
313+
decls, /*find_one=*/true);
314+
if (decls.empty())
315+
return node;
316+
317+
std::vector<lldb_private::CompilerContext> declContext =
318+
decls[0].GetDeclContext();
319+
320+
lldbassert(!declContext.empty() &&
321+
"Unexpected decl context for $ODI$ typealiased type");
322+
if (declContext.empty())
323+
return node;
324+
325+
auto module_context = declContext[0];
326+
327+
auto module_tranformer =
328+
[&](NodePointer module_node,
329+
CompilerContext module_context) -> NodePointer {
330+
if (module_node->getText() == swift::MANGLING_MODULE_OBJC)
331+
return module_node;
332+
333+
// If the mangled name's module and module context module match then
334+
// there's nothing to do.
335+
if (module_node->getText() == module_context.name)
336+
return module_node;
337+
338+
// Otherwise this is a type who is originally defined in a separate
339+
// module. Adjust the module name.
340+
auto *adjusted_module_node = dem.createNodeWithAllocatedText(
341+
Node::Kind::Module, module_context.name);
342+
did_transform = true;
343+
return adjusted_module_node;
344+
};
345+
346+
NodePointer transformed_module =
347+
TypeSystemSwiftTypeRef::TransformModuleName(
348+
node, dem, [&](NodePointer module_node) {
349+
return module_tranformer(module_node, module_context);
350+
});
351+
352+
if (!transformed_module) {
353+
return node;
354+
}
355+
356+
NodePointer transformed_generic_types =
357+
TypeSystemSwiftTypeRef::TransformBoundGenericTypes(
358+
dem, transformed_module, transform_all_module_nodes);
359+
return transformed_generic_types;
360+
};
361+
362+
auto transformed_type_node = transform_all_module_nodes(type_node);
363+
if (!did_transform)
364+
return {};
365+
366+
auto mangling =
367+
mangleNode(swift_demangle::mangleType(dem, transformed_type_node));
368+
assert(mangling.isSuccess());
369+
if (!mangling.isSuccess()) {
370+
LLDB_LOG(GetLog(LLDBLog::Types),
371+
"[AdjustTypeForOriginallyDefinedInModule] Unexpected mangling "
372+
"error when mangling adjusted node for type with mangled name {0}",
373+
mangled_typename);
374+
375+
return {};
376+
}
377+
378+
auto str = mangling.result();
379+
return str;
380+
}
381+
153382
llvm::StringRef
154383
TypeSystemSwiftTypeRef::GetBaseName(swift::Demangle::NodePointer node) {
155384
if (!node)
@@ -935,13 +1164,7 @@ swift::Demangle::NodePointer TypeSystemSwiftTypeRef::Transform(
9351164
}
9361165
if (changed) {
9371166
// Create a new node with the transformed children.
938-
auto kind = node->getKind();
939-
if (node->hasText())
940-
node = dem.createNodeWithAllocatedText(kind, node->getText());
941-
else if (node->hasIndex())
942-
node = dem.createNode(kind, node->getIndex());
943-
else
944-
node = dem.createNode(kind);
1167+
node = CloneNode(dem, node, /*set_children=*/false);
9451168
for (NodePointer transformed_child : children)
9461169
node->addChild(transformed_child, dem);
9471170
}
@@ -4830,6 +5053,7 @@ TypeSystemSwiftTypeRef::GetDependentGenericParamListForType(
48305053

48315054
#ifndef NDEBUG
48325055
bool TypeSystemSwiftTypeRef::ShouldSkipValidation(opaque_compiler_type_t type) {
5056+
return true;
48335057
auto mangled_name = GetMangledTypeName(type);
48345058
// NSNotificationName is a typedef to a NSString in clang type, but it's a
48355059
// struct in SwiftASTContext. Skip validation in this case.

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,34 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
366366
CanonicalizeSugar(swift::Demangle::Demangler &dem,
367367
swift::Demangle::NodePointer node);
368368

369+
/// Transforms the module name in the mangled type name using module_name_map
370+
/// as the mapping source.
371+
static swift::Demangle::ManglingErrorOr<std::string>
372+
TransformModuleName(llvm::StringRef mangled_name,
373+
const llvm::StringMap<llvm::StringRef> &module_name_map);
374+
375+
/// Given a node pointer to a type, transforms the module name of the type's
376+
/// demangle tree by applying \module_transformer to the module node.
377+
static swift::Demangle::NodePointer TransformModuleName(
378+
swift::Demangle::NodePointer node, swift::Demangle::Demangler &dem,
379+
std::function<swift::Demangle::NodePointer(swift::Demangle::NodePointer)>
380+
module_transformer);
381+
382+
/// Transforms the bound generic types of \node by applying \type_transformer
383+
/// to them.
384+
static swift::Demangle::NodePointer TransformBoundGenericTypes(
385+
swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node,
386+
std::function<swift::Demangle::NodePointer(swift::Demangle::NodePointer)>
387+
type_transformer);
388+
389+
/// Types with the @_originallyDefinedIn attribute are serialized with with
390+
/// the original module name in reflection metadata. At the same time the type
391+
/// is serialized with the swiftmodule name in debug info, but with a parent
392+
/// module with the original module name. This function adjusts \type to look
393+
/// up the type in reflection metadata if necessary.
394+
std::string
395+
AdjustTypeForOriginallyDefinedInModule(llvm::StringRef mangled_typename);
396+
369397
/// Return the canonicalized Demangle tree for a Swift mangled type name.
370398
swift::Demangle::NodePointer
371399
GetCanonicalDemangleTree(swift::Demangle::Demangler &dem,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules

0 commit comments

Comments
 (0)