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 <string.h>
#include "llvm/ADT/ArrayRef.h"
#include "swift/Strings.h"
#include "swift/Runtime/Config.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/ABI/System.h"
@@ -2344,6 +2345,9 @@ using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;
template<typename Runtime>
struct TargetGenericContext;
template<typename Runtime>
struct TargetModuleContextDescriptor;
/// Base class for all context descriptors.
template<typename Runtime>
struct TargetContextDescriptor {
@@ -2361,6 +2365,12 @@ struct TargetContextDescriptor {
/// context is not generic.
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 {
auto *genericContext = getGenericContext();
return genericContext
@@ -2376,12 +2386,24 @@ private:
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.
template<typename Runtime>
struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
/// The module 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) {
return cd->getKind() == ContextDescriptorKind::Module;
}
@@ -2389,6 +2411,21 @@ struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
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>
struct TargetGenericContextDescriptorHeader {
uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;

View File

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

View File

@@ -1291,15 +1291,171 @@ private:
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) {
auto parentAddress =
resolveNullableRelativeIndirectableField(base, base->Parent);
if (!parentAddress)
return None;
if (!*parentAddress)
return ContextDescriptorRef(nullptr);
if (auto parentDescriptor = readContextDescriptor(*parentAddress))
return parentDescriptor;
return None;
}
if (parentAddress) {
return readContextDescriptor(*parentAddress);
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;
std::string nodeName;
std::string relatedTag;
Demangle::Node::Kind nodeKind;
auto getTypeName = [&]() -> bool {
auto typeBuffer =
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
(descriptor.getLocalBuffer());
auto nameAddress = resolveRelativeField(descriptor, typeBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return false;
if (typeBuffer->isSynthesizedRelatedEntity()) {
nameAddress += nodeName.size() + 1;
if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
return false;
}
return true;
};
bool isTypeContext = false;
switch (auto contextKind = descriptor->getKind()) {
case ContextDescriptorKind::Class:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Class;
isTypeContext = true;
break;
case ContextDescriptorKind::Struct:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Structure;
isTypeContext = true;
break;
case ContextDescriptorKind::Enum:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Enum;
isTypeContext = true;
break;
case ContextDescriptorKind::Protocol: {
auto protocolBuffer =
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
(descriptor.getLocalBuffer());
auto nameAddress = resolveRelativeField(descriptor, protocolBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr;
nodeKind = Demangle::Node::Kind::Protocol;
break;
}
case ContextDescriptorKind::Extension:
// TODO: Remangle something about the extension context here.
return nullptr;
case ContextDescriptorKind::Anonymous:
// TODO: Remangle something about the anonymous context here.
return nullptr;
case ContextDescriptorKind::Module: {
// Modules shouldn't have a parent.
if (parentDemangling) {
return nullptr;
}
nodeKind = Demangle::Node::Kind::Module;
auto moduleBuffer =
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>
(descriptor.getLocalBuffer());
auto nameAddress
= resolveRelativeField(descriptor, moduleBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr;
// 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:
// Not a kind of context we know about.
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.
if (isTypeContext) {
auto typeFlags =
TypeContextDescriptorFlags(descriptor->Flags.getKindSpecificFlags());
if (typeFlags.isCTypedef())
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,
std::move(nodeName));
if (!relatedTag.empty()) {
auto relatedNode =
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
relatedNode->addChild(nameNode, nodeFactory);
nameNode = relatedNode;
}
auto demangling = nodeFactory.createNode(nodeKind);
demangling->addChild(parentDemangling, nodeFactory);
demangling->addChild(nameNode, nodeFactory);
return demangling;
}
/// Given a read nominal type descriptor, attempt to build a demangling tree
@@ -1307,129 +1463,10 @@ private:
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 relatedTag;
Demangle::Node::Kind nodeKind;
auto getTypeName = [&]() -> bool {
auto typeBuffer =
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
(parent.getLocalBuffer());
auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return false;
if (typeBuffer->isSynthesizedRelatedEntity()) {
nameAddress += nodeName.size() + 1;
if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
return false;
}
return true;
};
bool isTypeContext = false;
switch (auto contextKind = parent->getKind()) {
case ContextDescriptorKind::Class:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Class;
isTypeContext = true;
break;
case ContextDescriptorKind::Struct:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Structure;
isTypeContext = true;
break;
case ContextDescriptorKind::Enum:
if (!getTypeName())
return nullptr;
nodeKind = Demangle::Node::Kind::Enum;
isTypeContext = true;
break;
case ContextDescriptorKind::Protocol: {
auto protocolBuffer =
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
(parent.getLocalBuffer());
auto nameAddress = resolveRelativeField(parent, protocolBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr;
nodeKind = Demangle::Node::Kind::Protocol;
break;
}
case ContextDescriptorKind::Extension:
// TODO: Remangle something about the extension context here.
return nullptr;
case ContextDescriptorKind::Anonymous:
// TODO: Remangle something about the anonymous context here.
return nullptr;
case ContextDescriptorKind::Module: {
nodeKind = Demangle::Node::Kind::Module;
auto moduleBuffer =
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>(
parent.getLocalBuffer());
auto nameAddress
= resolveRelativeField(parent, moduleBuffer->Name);
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
return nullptr;
break;
}
default:
// Not a kind of context we know about.
return nullptr;
}
// Override the node kind if this was a Clang-imported type.
if (isTypeContext) {
auto typeFlags =
TypeContextDescriptorFlags(parent->Flags.getKindSpecificFlags());
if (typeFlags.isCTag())
nodeKind = Demangle::Node::Kind::Structure;
else if (typeFlags.isCTypedef())
nodeKind = Demangle::Node::Kind::TypeAlias;
}
auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
nodeName);
if (!relatedTag.empty()) {
auto relatedNode =
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
relatedNode->addChild(nameNode, nodeFactory);
nameNode = relatedNode;
}
nameComponents.emplace_back(nodeKind, nameNode);
parent = readParentContextDescriptor(parent);
}
// We should have made our way up to a module context.
if (nameComponents.empty())
auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
if (!demangling)
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);
top->addChild(demangling, nodeFactory);
return top;

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
// a stable mangling.
auto typeFlags = type->getTypeContextDescriptorFlags();
if (typeFlags.isCTag()) {
nodeKind = Node::Kind::Structure;
} else if (typeFlags.isCTypedef()) {
if (typeFlags.isCTypedef()) {
nodeKind = Node::Kind::TypeAlias;
} else if (nodeKind != Node::Kind::Structure &&
isCImportedTagType(type)) {
nodeKind = Node::Kind::Structure;
}
auto typeNode = Dem.createNode(nodeKind);

View File

@@ -153,6 +153,24 @@ static const TypeContextDescriptor *
_findNominalTypeDescriptor(Demangle::NodePointer node,
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
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
Demangle::NodePointer node) {
@@ -254,8 +272,11 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
case Demangle::Node::Kind::OtherNominalType:
break;
case Demangle::Node::Kind::Structure:
if (type->getKind() != ContextDescriptorKind::Struct
&& !type->getTypeContextDescriptorFlags().isCTag())
// We allow non-structs to match Kind::Structure if they are
// 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;
break;
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.
///
/// \param value - can be null, in which case the question should