Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2018-07-30 21:29:25 -07:00
6 changed files with 230 additions and 134 deletions

View File

@@ -28,6 +28,7 @@
#include <utility> #include <utility>
#include <string.h> #include <string.h>
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "swift/Strings.h"
#include "swift/Runtime/Config.h" #include "swift/Runtime/Config.h"
#include "swift/ABI/MetadataValues.h" #include "swift/ABI/MetadataValues.h"
#include "swift/ABI/System.h" #include "swift/ABI/System.h"
@@ -2344,6 +2345,9 @@ using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;
template<typename Runtime> template<typename Runtime>
struct TargetGenericContext; struct TargetGenericContext;
template<typename Runtime>
struct TargetModuleContextDescriptor;
/// Base class for all context descriptors. /// Base class for all context descriptors.
template<typename Runtime> template<typename Runtime>
struct TargetContextDescriptor { struct TargetContextDescriptor {
@@ -2361,6 +2365,12 @@ struct TargetContextDescriptor {
/// context is not generic. /// context is not generic.
const TargetGenericContext<Runtime> *getGenericContext() const; const TargetGenericContext<Runtime> *getGenericContext() const;
/// Get the module context for this context.
const TargetModuleContextDescriptor<Runtime> *getModuleContext() const;
/// Is this context part of a C-imported module?
bool isCImportedContext() const;
unsigned getNumGenericParams() const { unsigned getNumGenericParams() const {
auto *genericContext = getGenericContext(); auto *genericContext = getGenericContext();
return genericContext return genericContext
@@ -2376,12 +2386,24 @@ private:
using ContextDescriptor = TargetContextDescriptor<InProcess>; using ContextDescriptor = TargetContextDescriptor<InProcess>;
inline bool isCImportedModuleName(StringRef name) {
// This does not include MANGLING_MODULE_CLANG_IMPORTER because that's
// used only for synthesized declarations and not actual imported
// declarations.
return name == MANGLING_MODULE_OBJC;
}
/// Descriptor for a module context. /// Descriptor for a module context.
template<typename Runtime> template<typename Runtime>
struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> { struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
/// The module name. /// The module name.
RelativeDirectPointer<const char, /*nullable*/ false> Name; RelativeDirectPointer<const char, /*nullable*/ false> Name;
/// Is this module a special C-imported module?
bool isCImportedContext() const {
return isCImportedModuleName(Name.get());
}
static bool classof(const TargetContextDescriptor<Runtime> *cd) { static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Module; return cd->getKind() == ContextDescriptorKind::Module;
} }
@@ -2389,6 +2411,21 @@ struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>; using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;
template<typename Runtime>
inline bool TargetContextDescriptor<Runtime>::isCImportedContext() const {
return getModuleContext()->isCImportedContext();
}
template<typename Runtime>
inline const TargetModuleContextDescriptor<Runtime> *
TargetContextDescriptor<Runtime>::getModuleContext() const {
// All context chains should eventually find a module.
for (auto cur = this; true; cur = cur->Parent.get()) {
if (auto module = dyn_cast<TargetModuleContextDescriptor<Runtime>>(cur))
return module;
}
}
template<typename Runtime> template<typename Runtime>
struct TargetGenericContextDescriptorHeader { struct TargetGenericContextDescriptorHeader {
uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments; uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;

View File

@@ -1321,9 +1321,6 @@ public:
getImportNamespace, getImportNamespace,
setImportNamespace) setImportNamespace)
bool isCTag() const {
return getImportNamespace() == CTag;
}
bool isCTypedef() const { bool isCTypedef() const {
return getImportNamespace() == CTypedef; return getImportNamespace() == CTypedef;
} }

View File

@@ -1291,27 +1291,51 @@ private:
return ContextDescriptorRef(address, descriptor); return ContextDescriptorRef(address, descriptor);
} }
ContextDescriptorRef /// Returns Optional(nullptr) if there's no parent descriptor.
/// Returns None if there was an error reading the parent descriptor.
Optional<ContextDescriptorRef>
readParentContextDescriptor(ContextDescriptorRef base) { readParentContextDescriptor(ContextDescriptorRef base) {
auto parentAddress = auto parentAddress =
resolveNullableRelativeIndirectableField(base, base->Parent); resolveNullableRelativeIndirectableField(base, base->Parent);
if (!parentAddress)
if (parentAddress) { return None;
return readContextDescriptor(*parentAddress); if (!*parentAddress)
return ContextDescriptorRef(nullptr);
if (auto parentDescriptor = readContextDescriptor(*parentAddress))
return parentDescriptor;
return None;
} }
static bool isCImportedContext(Demangle::NodePointer node) {
do {
if (node->getKind() == Demangle::Node::Kind::Module) {
return isCImportedModuleName(node->getText());
}
// Continue to the parent.
node = node->getChild(0);
} while (node);
return false;
}
Demangle::NodePointer
buildContextDescriptorMangling(ContextDescriptorRef descriptor,
Demangle::NodeFactory &nodeFactory) {
// Read the parent descriptor.
auto parentDescriptorResult = readParentContextDescriptor(descriptor);
// If there was a problem reading the parent descriptor, we're done.
if (!parentDescriptorResult) return nullptr;
// Try to produce a mangle-tree for the parent.
Demangle::NodePointer parentDemangling = nullptr;
if (auto parentDescriptor = *parentDescriptorResult) {
parentDemangling =
buildContextDescriptorMangling(parentDescriptor, nodeFactory);
if (!parentDemangling)
return nullptr; return nullptr;
} }
/// Given a read nominal type descriptor, attempt to build a demangling tree
/// for it.
Demangle::NodePointer
buildNominalTypeMangling(ContextDescriptorRef descriptor,
Demangle::NodeFactory &nodeFactory) {
std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
nameComponents;
ContextDescriptorRef parent = descriptor;
while (parent) {
std::string nodeName; std::string nodeName;
std::string relatedTag; std::string relatedTag;
Demangle::Node::Kind nodeKind; Demangle::Node::Kind nodeKind;
@@ -1319,8 +1343,8 @@ private:
auto getTypeName = [&]() -> bool { auto getTypeName = [&]() -> bool {
auto typeBuffer = auto typeBuffer =
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *> reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
(parent.getLocalBuffer()); (descriptor.getLocalBuffer());
auto nameAddress = resolveRelativeField(parent, typeBuffer->Name); auto nameAddress = resolveRelativeField(descriptor, typeBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName)) if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return false; return false;
@@ -1334,7 +1358,7 @@ private:
}; };
bool isTypeContext = false; bool isTypeContext = false;
switch (auto contextKind = parent->getKind()) { switch (auto contextKind = descriptor->getKind()) {
case ContextDescriptorKind::Class: case ContextDescriptorKind::Class:
if (!getTypeName()) if (!getTypeName())
return nullptr; return nullptr;
@@ -1356,8 +1380,8 @@ private:
case ContextDescriptorKind::Protocol: { case ContextDescriptorKind::Protocol: {
auto protocolBuffer = auto protocolBuffer =
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *> reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
(parent.getLocalBuffer()); (descriptor.getLocalBuffer());
auto nameAddress = resolveRelativeField(parent, protocolBuffer->Name); auto nameAddress = resolveRelativeField(descriptor, protocolBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName)) if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr; return nullptr;
@@ -1373,15 +1397,23 @@ private:
return nullptr; return nullptr;
case ContextDescriptorKind::Module: { case ContextDescriptorKind::Module: {
// Modules shouldn't have a parent.
if (parentDemangling) {
return nullptr;
}
nodeKind = Demangle::Node::Kind::Module; nodeKind = Demangle::Node::Kind::Module;
auto moduleBuffer = auto moduleBuffer =
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>( reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>
parent.getLocalBuffer()); (descriptor.getLocalBuffer());
auto nameAddress auto nameAddress
= resolveRelativeField(parent, moduleBuffer->Name); = resolveRelativeField(descriptor, moduleBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName)) if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr; return nullptr;
break;
// The form of module contexts is a little different from other
// contexts; just create the node directly here and return.
return nodeFactory.createNode(nodeKind, std::move(nodeName));
} }
default: default:
@@ -1389,19 +1421,30 @@ private:
return nullptr; return nullptr;
} }
// The root context should be a module context, which we handled directly
// in the switch, so if we got here without a parent, we're ill-formed.
if (!parentDemangling) {
return nullptr;
}
// Override the node kind if this was a Clang-imported type. // Override the node kind if this was a Clang-imported type.
if (isTypeContext) { if (isTypeContext) {
auto typeFlags = auto typeFlags =
TypeContextDescriptorFlags(parent->Flags.getKindSpecificFlags()); TypeContextDescriptorFlags(descriptor->Flags.getKindSpecificFlags());
if (typeFlags.isCTag()) if (typeFlags.isCTypedef())
nodeKind = Demangle::Node::Kind::Structure;
else if (typeFlags.isCTypedef())
nodeKind = Demangle::Node::Kind::TypeAlias; nodeKind = Demangle::Node::Kind::TypeAlias;
// As a special case, always use the struct mangling for C-imported
// value types.
else if (nodeKind == Demangle::Node::Kind::Enum &&
!typeFlags.isSynthesizedRelatedEntity() &&
isCImportedContext(parentDemangling))
nodeKind = Demangle::Node::Kind::Structure;
} }
auto nameNode = nodeFactory.createNode(Node::Kind::Identifier, auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
nodeName); std::move(nodeName));
if (!relatedTag.empty()) { if (!relatedTag.empty()) {
auto relatedNode = auto relatedNode =
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag); nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
@@ -1409,26 +1452,20 @@ private:
nameNode = relatedNode; nameNode = relatedNode;
} }
nameComponents.emplace_back(nodeKind, nameNode); auto demangling = nodeFactory.createNode(nodeKind);
demangling->addChild(parentDemangling, nodeFactory);
parent = readParentContextDescriptor(parent); demangling->addChild(nameNode, nodeFactory);
return demangling;
} }
// We should have made our way up to a module context. /// Given a read nominal type descriptor, attempt to build a demangling tree
if (nameComponents.empty()) /// for it.
Demangle::NodePointer
buildNominalTypeMangling(ContextDescriptorRef descriptor,
Demangle::NodeFactory &nodeFactory) {
auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
if (!demangling)
return nullptr; return nullptr;
if (nameComponents.back().first != Node::Kind::Module)
return nullptr;
auto moduleInfo = std::move(nameComponents.back());
nameComponents.pop_back();
auto demangling =
nodeFactory.createNode(Node::Kind::Module, moduleInfo.second->getText());
for (auto &component : reversed(nameComponents)) {
auto parent = nodeFactory.createNode(component.first);
parent->addChild(demangling, nodeFactory);
parent->addChild(component.second, nodeFactory);
demangling = parent;
}
auto top = nodeFactory.createNode(Node::Kind::Type); auto top = nodeFactory.createNode(Node::Kind::Type);
top->addChild(demangling, nodeFactory); top->addChild(demangling, nodeFactory);

View File

@@ -165,10 +165,11 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
// Override the node kind if this is a Clang-imported type so we give it // Override the node kind if this is a Clang-imported type so we give it
// a stable mangling. // a stable mangling.
auto typeFlags = type->getTypeContextDescriptorFlags(); auto typeFlags = type->getTypeContextDescriptorFlags();
if (typeFlags.isCTag()) { if (typeFlags.isCTypedef()) {
nodeKind = Node::Kind::Structure;
} else if (typeFlags.isCTypedef()) {
nodeKind = Node::Kind::TypeAlias; nodeKind = Node::Kind::TypeAlias;
} else if (nodeKind != Node::Kind::Structure &&
isCImportedTagType(type)) {
nodeKind = Node::Kind::Structure;
} }
auto typeNode = Dem.createNode(nodeKind); auto typeNode = Dem.createNode(nodeKind);

View File

@@ -153,6 +153,24 @@ static const TypeContextDescriptor *
_findNominalTypeDescriptor(Demangle::NodePointer node, _findNominalTypeDescriptor(Demangle::NodePointer node,
Demangle::Demangler &Dem); Demangle::Demangler &Dem);
bool swift::isCImportedTagType(const TypeContextDescriptor *type) {
// Tag types are always imported as structs or enums.
if (type->getKind() != ContextDescriptorKind::Enum &&
type->getKind() != ContextDescriptorKind::Struct)
return false;
// Not a typedef imported as a nominal type.
if (type->getTypeContextDescriptorFlags().isCTypedef())
return false;
// Not a related entity.
if (type->isSynthesizedRelatedEntity())
return false;
// Imported from C.
return type->Parent->isCImportedContext();
}
bool bool
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context, swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
Demangle::NodePointer node) { Demangle::NodePointer node) {
@@ -254,8 +272,11 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
case Demangle::Node::Kind::OtherNominalType: case Demangle::Node::Kind::OtherNominalType:
break; break;
case Demangle::Node::Kind::Structure: case Demangle::Node::Kind::Structure:
if (type->getKind() != ContextDescriptorKind::Struct // We allow non-structs to match Kind::Structure if they are
&& !type->getTypeContextDescriptorFlags().isCTag()) // imported C tag types. This is necessary because we artificially
// make imported C tag types Kind::Structure.
if (type->getKind() != ContextDescriptorKind::Struct &&
!isCImportedTagType(type))
return false; return false;
break; break;
case Demangle::Node::Kind::Class: case Demangle::Node::Kind::Class:

View File

@@ -314,6 +314,9 @@ public:
} }
}; };
/// Is the given type imported from a C tag type?
bool isCImportedTagType(const TypeContextDescriptor *type);
/// Check whether a type conforms to a protocol. /// Check whether a type conforms to a protocol.
/// ///
/// \param value - can be null, in which case the question should /// \param value - can be null, in which case the question should