Level : WORDPRESS BOOK LINKEDIN PATENT Send Mail 동냥하기 hajunho.com

nodepointer

Python3 / / 2020. 7. 1. 00:02
https://github.com/apple/swift/blob/master/stdlib/public/runtime/Demangle.cpp

//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/Range.h"
#include "swift/ABI/TypeIdentity.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Portability.h"
#include "swift/Strings.h"
#include "Private.h"
#include <vector>
#if SWIFT_OBJC_INTEROP
#include <objc/runtime.h>
#endif
using namespace swift;
Demangle::NodePointer
swift::_buildDemanglingForContext(const ContextDescriptor *context,
llvm::ArrayRef<NodePointer> demangledGenerics,
Demangle::Demangler &Dem) {
unsigned usedDemangledGenerics = 0;
NodePointer node = nullptr;
// Walk up the context tree.
std::vector<const ContextDescriptor *> descriptorPath;
{
const ContextDescriptor *parent = context;
while (parent) {
descriptorPath.push_back(parent);
parent = parent->Parent;
}
}
auto getGenericArgsTypeListForContext =
[&](const ContextDescriptor *context) -> NodePointer {
if (demangledGenerics.empty())
return nullptr;
if (context->getKind() == ContextDescriptorKind::Anonymous)
return nullptr;
auto generics = context->getGenericContext();
if (!generics)
return nullptr;
auto numParams = generics->getGenericContextHeader().NumParams;
if (numParams <= usedDemangledGenerics)
return nullptr;
auto genericArgsList = Dem.createNode(Node::Kind::TypeList);
for (unsigned e = generics->getGenericContextHeader().NumParams;
usedDemangledGenerics < e;
++usedDemangledGenerics) {
genericArgsList->addChild(demangledGenerics[usedDemangledGenerics],
Dem);
}
return genericArgsList;
};
for (auto component : reversed(descriptorPath)) {
switch (auto kind = component->getKind()) {
case ContextDescriptorKind::Module: {
assert(node == nullptr && "module should be top level");
auto name = llvm::cast<ModuleContextDescriptor>(component)->Name.get();
node = Dem.createNode(Node::Kind::Module, name);
break;
}
case ContextDescriptorKind::Extension: {
auto extension = llvm::cast<ExtensionContextDescriptor>(component);
// Demangle the extension self type.
auto selfType = Dem.demangleType(extension->getMangledExtendedContext());
if (selfType->getKind() == Node::Kind::Type)
selfType = selfType->getChild(0);
// Substitute in the generic arguments.
auto genericArgsList = getGenericArgsTypeListForContext(component);
if (selfType->getKind() == Node::Kind::BoundGenericEnum
|| selfType->getKind() == Node::Kind::BoundGenericStructure
|| selfType->getKind() == Node::Kind::BoundGenericClass
|| selfType->getKind() == Node::Kind::BoundGenericOtherNominalType) {
if (genericArgsList) {
auto substSelfType = Dem.createNode(selfType->getKind());
substSelfType->addChild(selfType->getChild(0), Dem);
substSelfType->addChild(genericArgsList, Dem);
selfType = substSelfType;
} else {
// TODO: Use the unsubstituted type if we can't handle the
// substitutions yet.
selfType = selfType->getChild(0)->getChild(0);
}
}
auto extNode = Dem.createNode(Node::Kind::Extension);
extNode->addChild(node, Dem);
extNode->addChild(selfType, Dem);
// TODO: Turn the generic signature into a demangling as the third
// generic argument.
node = extNode;
break;
}
case ContextDescriptorKind::Protocol: {
auto protocol = llvm::cast<ProtocolDescriptor>(component);
auto name = protocol->Name.get();
auto protocolNode = Dem.createNode(Node::Kind::Protocol);
protocolNode->addChild(node, Dem);
auto nameNode = Dem.createNode(Node::Kind::Identifier, name);
protocolNode->addChild(nameNode, Dem);
node = protocolNode;
break;
}
default:
// Form a type context demangling for type contexts.
if (auto type = llvm::dyn_cast<TypeContextDescriptor>(component)) {
auto identity = ParsedTypeIdentity::parse(type);
Node::Kind nodeKind;
Node::Kind genericNodeKind;
switch (kind) {
case ContextDescriptorKind::Class:
nodeKind = Node::Kind::Class;
genericNodeKind = Node::Kind::BoundGenericClass;
break;
case ContextDescriptorKind::Struct:
nodeKind = Node::Kind::Structure;
genericNodeKind = Node::Kind::BoundGenericStructure;
break;
case ContextDescriptorKind::Enum:
nodeKind = Node::Kind::Enum;
genericNodeKind = Node::Kind::BoundGenericEnum;
break;
default:
// We don't know about this kind of type. Use an "other type" mangling
// for it.
nodeKind = Node::Kind::OtherNominalType;
genericNodeKind = Node::Kind::BoundGenericOtherNominalType;
break;
}
// Override the node kind if this is a Clang-imported type so we give it
// a stable mangling.
if (identity.isCTypedef()) {
nodeKind = Node::Kind::TypeAlias;
} else if (nodeKind != Node::Kind::Structure &&
_isCImportedTagType(type, identity)) {
nodeKind = Node::Kind::Structure;
}
auto typeNode = Dem.createNode(nodeKind);
typeNode->addChild(node, Dem);
auto nameNode = Dem.createNode(Node::Kind::Identifier,
identity.getABIName());
if (identity.isAnyRelatedEntity()) {
auto relatedName = Dem.createNode(Node::Kind::RelatedEntityDeclName,
identity.getRelatedEntityName());
relatedName->addChild(nameNode, Dem);
nameNode = relatedName;
}
typeNode->addChild(nameNode, Dem);
node = typeNode;
// Apply generic arguments if the context is generic.
if (auto genericArgsList = getGenericArgsTypeListForContext(component)){
auto unspecializedType = Dem.createNode(Node::Kind::Type);
unspecializedType->addChild(node, Dem);
auto genericNode = Dem.createNode(genericNodeKind);
genericNode->addChild(unspecializedType, Dem);
genericNode->addChild(genericArgsList, Dem);
node = genericNode;
}
break;
}
// This runtime doesn't understand this context, or it's a context with
// no richer runtime information available about it (such as an anonymous
// context). Use an unstable mangling to represent the context by its
// pointer identity.
char addressBuf[sizeof(void*) * 2 + 1 + 1];
snprintf(addressBuf, sizeof(addressBuf), "$%" PRIxPTR, (uintptr_t)component);
auto anonNode = Dem.createNode(Node::Kind::AnonymousContext);
CharVector addressStr;
addressStr.append(addressBuf, Dem);
auto name = Dem.createNode(Node::Kind::Identifier, addressStr);
anonNode->addChild(name, Dem);
anonNode->addChild(node, Dem);
// Collect generic arguments if the context is generic.
auto genericArgsList = getGenericArgsTypeListForContext(component);
if (!genericArgsList)
genericArgsList = Dem.createNode(Node::Kind::TypeList);
anonNode->addChild(genericArgsList, Dem);
node = anonNode;
break;
}
}
// Wrap the final result in a top-level Type node.
auto top = Dem.createNode(Node::Kind::Type);
top->addChild(node, Dem);
return top;
}
// FIXME: This stuff should be merged with the existing logic in
// include/swift/Reflection/TypeRefBuilder.h as part of the rewrite
// to change stdlib reflection over to using remote mirrors.
Demangle::NodePointer
swift::_swift_buildDemanglingForMetadata(const Metadata *type,
Demangle::Demangler &Dem);
static Demangle::NodePointer
_buildDemanglerForBuiltinType(const Metadata *type, Demangle::Demangler &Dem) {
#define BUILTIN_TYPE(Symbol, Name) \
if (type == &METADATA_SYM(Symbol).base) \
return Dem.createNode(Node::Kind::BuiltinTypeName, Name);
#include "swift/Runtime/BuiltinTypes.def"
return nullptr;
}
/// Build a demangled type tree for a nominal type.
static Demangle::NodePointer
_buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
using namespace Demangle;
// Get the context descriptor from the type metadata.
const TypeContextDescriptor *description;
switch (type->getKind()) {
case MetadataKind::Class: {
auto classType = static_cast<const ClassMetadata *>(type);
#if SWIFT_OBJC_INTEROP
// Peek through artificial subclasses.
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
classType = classType->Superclass;
#endif
description = classType->getDescription();
break;
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
auto enumType = static_cast<const EnumMetadata *>(type);
description = enumType->Description;
break;
}
case MetadataKind::Struct: {
auto structType = static_cast<const StructMetadata *>(type);
description = structType->Description;
break;
}
case MetadataKind::ForeignClass: {
auto foreignType = static_cast<const ForeignClassMetadata *>(type);
description = foreignType->Description;
break;
}
default:
return nullptr;
}
// Gather the complete set of generic arguments that must be written to
// form this type.
std::vector<const Metadata *> allGenericArgs;
gatherWrittenGenericArgs(type, description, allGenericArgs);
// Demangle the generic arguments.
std::vector<NodePointer> demangledGenerics;
for (auto genericArg : allGenericArgs) {
// When there is no generic argument, put in a placeholder.
if (!genericArg) {
auto placeholder = Dem.createNode(Node::Kind::Tuple);
auto emptyList = Dem.createNode(Node::Kind::TypeList);
placeholder->addChild(emptyList, Dem);
auto type = Dem.createNode(Node::Kind::Type);
type->addChild(placeholder, Dem);
demangledGenerics.push_back(type);
continue;
}
// Demangle this argument.
auto genericArgDemangling =
_swift_buildDemanglingForMetadata(genericArg, Dem);
if (!genericArgDemangling)
return nullptr;
demangledGenerics.push_back(genericArgDemangling);
}
return _buildDemanglingForContext(description, demangledGenerics, Dem);
}
// Build a demangled type tree for a type.
//
// FIXME: This should use MetadataReader.h.
Demangle::NodePointer
swift::_swift_buildDemanglingForMetadata(const Metadata *type,
Demangle::Demangler &Dem) {
using namespace Demangle;
switch (type->getKind()) {
case MetadataKind::Class:
case MetadataKind::Enum:
case MetadataKind::Optional:
case MetadataKind::Struct:
case MetadataKind::ForeignClass:
return _buildDemanglingForNominalType(type, Dem);
case MetadataKind::ObjCClassWrapper: {
#if SWIFT_OBJC_INTEROP
auto objcWrapper = static_cast<const ObjCClassWrapperMetadata *>(type);
const char *className = class_getName(objcWrapper->getObjCClassObject());
auto module = Dem.createNode(Node::Kind::Module, MANGLING_MODULE_OBJC);
auto node = Dem.createNode(Node::Kind::Class);
node->addChild(module, Dem);
node->addChild(Dem.createNode(Node::Kind::Identifier,
llvm::StringRef(className)), Dem);
return node;
#else
assert(false && "no ObjC interop");
return nullptr;
#endif
}
case MetadataKind::Existential: {
auto exis = static_cast<const ExistentialTypeMetadata *>(type);
auto protocols = exis->getProtocols();
auto type_list = Dem.createNode(Node::Kind::TypeList);
auto proto_list = Dem.createNode(Node::Kind::ProtocolList);
proto_list->addChild(type_list, Dem);
// The protocol descriptors should be pre-sorted since the compiler will
// only ever make a swift_getExistentialTypeMetadata invocation using
// its canonical ordering of protocols.
for (auto protocol : protocols) {
#if SWIFT_OBJC_INTEROP
if (protocol.isObjC()) {
// The protocol name is mangled as a type symbol, with the _Tt prefix.
StringRef ProtoName(protocol.getName());
NodePointer protocolNode = Dem.demangleSymbol(ProtoName);
// ObjC protocol names aren't mangled.
if (!protocolNode) {
auto module = Dem.createNode(Node::Kind::Module,
MANGLING_MODULE_OBJC);
auto node = Dem.createNode(Node::Kind::Protocol);
node->addChild(module, Dem);
node->addChild(Dem.createNode(Node::Kind::Identifier, ProtoName),
Dem);
auto typeNode = Dem.createNode(Node::Kind::Type);
typeNode->addChild(node, Dem);
type_list->addChild(typeNode, Dem);
continue;
}
// Dig out the protocol node.
// Global -> (Protocol|TypeMangling)
protocolNode = protocolNode->getChild(0);
if (protocolNode->getKind() == Node::Kind::TypeMangling) {
protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
protocolNode = protocolNode->getChild(0); // TypeList -> Type
assert(protocolNode->getKind() == Node::Kind::Type);
assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
} else {
assert(protocolNode->getKind() == Node::Kind::Protocol);
}
type_list->addChild(protocolNode, Dem);
continue;
}
#endif
auto protocolNode =
_buildDemanglingForContext(protocol.getSwiftProtocol(), { }, Dem);
if (!protocolNode)
return nullptr;
type_list->addChild(protocolNode, Dem);
}
if (auto superclass = exis->getSuperclassConstraint()) {
// If there is a superclass constraint, we mangle it specially.
auto result = Dem.createNode(Node::Kind::ProtocolListWithClass);
auto superclassNode = _swift_buildDemanglingForMetadata(superclass, Dem);
result->addChild(proto_list, Dem);
result->addChild(superclassNode, Dem);
return result;
}
if (exis->isClassBounded()) {
// Check if the class constraint is implied by any of our
// protocols.
bool requiresClassImplicit = false;
for (auto protocol : protocols) {
if (protocol.getClassConstraint() == ProtocolClassConstraint::Class)
requiresClassImplicit = true;
}
// If it was implied, we don't do anything special.
if (requiresClassImplicit)
return proto_list;
// If the existential type has an explicit AnyObject constraint,
// we must mangle it as such.
auto result = Dem.createNode(Node::Kind::ProtocolListWithAnyObject);
result->addChild(proto_list, Dem);
return result;
}
// Just a simple composition of protocols.
return proto_list;
}
case MetadataKind::ExistentialMetatype: {
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,
Dem);
auto node = Dem.createNode(Node::Kind::ExistentialMetatype);
node->addChild(instance, Dem);
return node;
}
case MetadataKind::Function: {
auto func = static_cast<const FunctionTypeMetadata *>(type);
Node::Kind kind;
switch (func->getConvention()) {
case FunctionMetadataConvention::Swift:
if (!func->isEscaping())
kind = Node::Kind::NoEscapeFunctionType;
else
kind = Node::Kind::FunctionType;
break;
case FunctionMetadataConvention::Block:
kind = Node::Kind::ObjCBlock;
break;
case FunctionMetadataConvention::CFunctionPointer:
kind = Node::Kind::CFunctionPointer;
break;
case FunctionMetadataConvention::Thin:
kind = Node::Kind::ThinFunctionType;
break;
}
std::vector<std::pair<NodePointer, bool>> inputs;
for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
auto param = func->getParameter(i);
auto flags = func->getParameterFlags(i);
auto input = _swift_buildDemanglingForMetadata(param, Dem);
auto wrapInput = [&](Node::Kind kind) {
auto parent = Dem.createNode(kind);
parent->addChild(input, Dem);
input = parent;
};
switch (flags.getValueOwnership()) {
case ValueOwnership::Default:
/* nothing */
break;
case ValueOwnership::InOut:
wrapInput(Node::Kind::InOut);
break;
case ValueOwnership::Shared:
wrapInput(Node::Kind::Shared);
break;
case ValueOwnership::Owned:
wrapInput(Node::Kind::Owned);
break;
}
inputs.push_back({input, flags.isVariadic()});
}
NodePointer totalInput = nullptr;
switch (inputs.size()) {
case 1: {
auto singleParam = inputs.front();
// If the sole unlabeled parameter has a non-tuple type, encode
// the parameter list as a single type.
if (!singleParam.second) {
auto singleType = singleParam.first;
if (singleType->getKind() == Node::Kind::Type)
singleType = singleType->getFirstChild();
if (singleType->getKind() != Node::Kind::Tuple) {
totalInput = singleParam.first;
break;
}
}
// Otherwise it requires a tuple wrapper.
LLVM_FALLTHROUGH;
}
// This covers both none and multiple parameters.
default:
auto tuple = Dem.createNode(Node::Kind::Tuple);
for (auto &input : inputs) {
NodePointer eltType;
bool isVariadic;
std::tie(eltType, isVariadic) = input;
// Tuple element := variadic-marker label? type
auto tupleElt = Dem.createNode(Node::Kind::TupleElement);
if (isVariadic)
tupleElt->addChild(Dem.createNode(Node::Kind::VariadicMarker), Dem);
if (eltType->getKind() == Node::Kind::Type) {
tupleElt->addChild(eltType, Dem);
} else {
auto type = Dem.createNode(Node::Kind::Type);
type->addChild(eltType, Dem);
tupleElt->addChild(type, Dem);
}
tuple->addChild(tupleElt, Dem);
}
totalInput = tuple;
break;
}
NodePointer parameters = Dem.createNode(Node::Kind::ArgumentTuple);
NodePointer paramType = Dem.createNode(Node::Kind::Type);
paramType->addChild(totalInput, Dem);
parameters->addChild(paramType, Dem);
NodePointer resultTy = _swift_buildDemanglingForMetadata(func->ResultType,
Dem);
NodePointer result = Dem.createNode(Node::Kind::ReturnType);
result->addChild(resultTy, Dem);
auto funcNode = Dem.createNode(kind);
if (func->throws())
funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
funcNode->addChild(parameters, Dem);
funcNode->addChild(result, Dem);
return funcNode;
}
case MetadataKind::Metatype: {
auto metatype = static_cast<const MetatypeMetadata *>(type);
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType,
Dem);
auto typeNode = Dem.createNode(Node::Kind::Type);
typeNode->addChild(instance, Dem);
auto node = Dem.createNode(Node::Kind::Metatype);
node->addChild(typeNode, Dem);
return node;
}
case MetadataKind::Tuple: {
auto tuple = static_cast<const TupleTypeMetadata *>(type);
const char *labels = tuple->Labels;
auto tupleNode = Dem.createNode(Node::Kind::Tuple);
for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
auto elt = Dem.createNode(Node::Kind::TupleElement);
// Add a label child if applicable:
if (labels) {
// Look for the next space in the labels string.
if (const char *space = strchr(labels, ' ')) {
// If there is one, and the label isn't empty, add a label child.
if (labels != space) {
auto eltName =
Dem.createNode(Node::Kind::TupleElementName,
llvm::StringRef(labels, space - labels));
elt->addChild(eltName, Dem);
}
// Skip past the space.
labels = space + 1;
}
}
// Add the element type child.
auto eltType =
_swift_buildDemanglingForMetadata(tuple->getElement(i).Type, Dem);
if (eltType->getKind() == Node::Kind::Type) {
elt->addChild(eltType, Dem);
} else {
auto type = Dem.createNode(Node::Kind::Type);
type->addChild(eltType, Dem);
elt->addChild(type, Dem);
}
// Add the completed element to the tuple.
tupleNode->addChild(elt, Dem);
}
return tupleNode;
}
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
break;
case MetadataKind::Opaque:
default: {
if (auto builtinType = _buildDemanglerForBuiltinType(type, Dem))
return builtinType;
// FIXME: Some opaque types do have manglings, but we don't have enough info
// to figure them out.
break;
}
}
// Not a type.
return nullptr;
}
// NB: This function is not used directly in the Swift codebase, but is
// exported for Xcode support and is used by the sanitizers. Please coordinate
// before changing.
char *swift_demangle(const char *mangledName,
size_t mangledNameLength,
char *outputBuffer,
size_t *outputBufferSize,
uint32_t flags) {
if (flags != 0) {
swift::fatalError(0, "Only 'flags' value of '0' is currently supported.");
}
if (outputBuffer != nullptr && outputBufferSize == nullptr) {
swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'.");
}
// Check if we are dealing with Swift mangled name, otherwise, don't try
// to demangle and send indication to the user.
if (!Demangle::isSwiftSymbol(mangledName))
return nullptr; // Not a mangled name
// Demangle the name.
auto options = Demangle::DemangleOptions();
options.DisplayDebuggerGeneratedModule = false;
auto result =
Demangle::demangleSymbolAsString(mangledName,
mangledNameLength,
options);
// If the output buffer is not provided, malloc memory ourselves.
if (outputBuffer == nullptr || *outputBufferSize == 0) {
return strdup(result.c_str());
}
// Indicate a failure if the result does not fit and will be truncated
// and set the required outputBufferSize.
if (*outputBufferSize < result.length() + 1) {
*outputBufferSize = result.length() + 1;
}
// Copy into the provided buffer.
_swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize);
return outputBuffer;
}



'Python3' 카테고리의 다른 글

텍스트를 이미지로 그려서 붙이기  (0) 2020.07.01
plist 읽기  (0) 2020.07.01
dropDown Menu  (2) 2020.07.01
UITabBar 크기 조정  (0) 2020.06.30
Making mater-detail app to hadle imageView  (0) 2020.06.23
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기