Merge pull request #20005 from DougGregor/more-symbolic-references
[ABI] Introduce indirect symbolic references to context descriptors.
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index d4bade7..93cb49d 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -9,9 +9,15 @@
--------
::
- mangled-name ::= '$s' global
+ mangled-name ::= '$s' global // Swift stable mangling
+ mangled-name ::= '_T0' global // Swift 4.0
+ mangled-name ::= '$S' global // Swift 4.2
-All Swift-mangled names begin with this prefix.
+All Swift-mangled names begin with a common prefix. Since Swift 4.0, the
+compiler has used variations of the mangling described in this document, though
+pre-stable versions may not exactly conform to this description. By using
+distinct prefixes, tools can attempt to accommodate bugs and version variations
+in pre-stable versions of Swift.
The basic mangling scheme is a list of 'operators' where the operators are
structured in a post-fix order. For example the mangling may start with an
@@ -20,8 +26,6 @@
4Test3FooC // The trailing 'C' says that 'Foo' is a class in module 'Test'
-
-
Operators are either identifiers or a sequence of one or more characters,
like ``C`` for class.
All operators share the same name-space. Important operators are a single
@@ -42,6 +46,48 @@
In the following, productions which are only _part_ of an operator, are
named with uppercase letters.
+Symbolic references
+~~~~~~~~~~~~~~~~~~~
+
+The Swift compiler emits mangled names into binary images to encode
+references to types for runtime instantiation and reflection. In a binary,
+these mangled names may embed pointers to runtime data
+structures in order to more efficiently represent locally-defined types.
+We call these pointers **symbolic references**.
+These references will be introduced by a control character in the range
+`\x01` ... `\x1F`, which indicates the kind of symbolic reference, followed by
+some number of arbitrary bytes *which may include null bytes*. Code that
+processes mangled names out of Swift binaries needs to be aware of symbolic
+references in order to properly terminate strings; a null terminator may be
+part of a symbolic reference.
+
+::
+
+ symbolic-reference ::= [\x01-\x17] .{4} // Relative symbolic reference
+ #if sizeof(void*) == 8
+ symbolic-reference ::= [\x18-\x1F] .{8} // Absolute symbolic reference
+ #elif sizeof(void*) == 4
+ symbolic-reference ::= [\x18-\x1F] .{4} // Absolute symbolic reference
+ #endif
+
+Symbolic references are only valid in compiler-emitted metadata structures
+and must only appear in read-only parts of a binary image. APIs and tools
+that interpret Swift mangled names from potentially uncontrolled inputs must
+refuse to interpret symbolic references.
+
+The following symbolic reference kinds are currently implemented:
+
+::
+
+ {any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
+ {any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
+ // The grammatical role of the symbolic reference is determined by the
+ // kind of context descriptor referenced
+
+ protocol-conformance-ref ::= '\x03' .{4} // Reference points directly to protocol conformance descriptor (NOT IMPLEMENTED)
+ protocol-conformance-ref ::= '\x04' .{4} // Reference points indirectly to protocol conformance descriptor (NOT IMPLEMENTED)
+
+
Globals
~~~~~~~
@@ -549,7 +595,9 @@
::
- protocol-conformance ::= type protocol module generic-signature?
+ protocol-conformance-context ::= protocol module generic-signature?
+
+ protocol-conformance ::= type protocol-conformance-context
``<protocol-conformance>`` refers to a type's conformance to a protocol. The
named module is the one containing the extension or type declaration that
@@ -557,12 +605,28 @@
::
+ protocol-conformance ::= type protocol
+
+If ``type`` is a generic parameter or associated type of one, then no module
+is mangled, because the conformance must be resolved from the generic
+environment.
+
protocol-conformance ::= context identifier protocol identifier generic-signature? // Property behavior conformance
Property behaviors are implemented using private protocol conformances.
::
+ concrete-protocol-conformance ::= type protocol-conformance-ref
+ protocol-conformance-ref ::= protocol module?
+
+A compact representation used to represent mangled protocol conformance witness
+arguments at runtime. The ``module`` is only specified for conformances that
+are "retroactive", meaning that the context in which the conformance is defined
+is in neither the protocol or type module.
+
+::
+
generic-signature ::= requirement* 'l' // one generic parameter
generic-signature ::= requirement* 'r' GENERIC-PARAM-COUNT* 'l'
diff --git a/include/swift/AST/ASTMangler.h b/include/swift/AST/ASTMangler.h
index 6b6f6bf..07c64f8 100644
--- a/include/swift/AST/ASTMangler.h
+++ b/include/swift/AST/ASTMangler.h
@@ -46,12 +46,22 @@
/// If disabled, it is an error to try to mangle such an entity.
bool AllowNamelessEntities = false;
- /// If nonnull, provides a callback to encode symbolic references to
- /// type contexts.
- std::function<bool (const DeclContext *Context)>
- CanSymbolicReference;
-
- std::vector<std::pair<const DeclContext *, unsigned>> SymbolicReferences;
+ /// If enabled, some entities will be emitted as symbolic reference
+ /// placeholders. The offsets of these references will be stored in the
+ /// `SymbolicReferences` vector, and it is up to the consumer of the mangling
+ /// to fill these in.
+ bool AllowSymbolicReferences = false;
+
+public:
+ using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
+ const ProtocolConformance *>;
+protected:
+
+ /// If set, the mangler calls this function to determine whether to symbolic
+ /// reference a given entity. Defaults to always returning true.
+ std::function<bool (SymbolicReferent)> CanSymbolicReference;
+
+ std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences;
public:
enum class SymbolKind {
@@ -292,7 +302,7 @@
void appendOpParamForLayoutConstraint(LayoutConstraint Layout);
- void appendSymbolicReference(const DeclContext *context);
+ void appendSymbolicReference(SymbolicReferent referent);
std::string mangleTypeWithoutPrefix(Type type) {
appendType(type);
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index 55f5347..7621fae 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -33,6 +33,8 @@
namespace swift {
namespace Demangle {
+enum class SymbolicReferenceKind : uint8_t;
+
struct DemangleOptions {
bool SynthesizeSugarOnTypes = false;
bool DisplayDebuggerGeneratedModule = true;
@@ -473,7 +475,9 @@
/// This should always round-trip perfectly with demangleSymbolAsNode.
std::string mangleNode(const NodePointer &root);
-using SymbolicResolver = llvm::function_ref<Demangle::NodePointer (const void *)>;
+using SymbolicResolver =
+ llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
+ const void *)>;
/// \brief Remangle a demangled parse tree, using a callback to resolve
/// symbolic references.
@@ -537,6 +541,8 @@
return std::move(*this << std::forward<T>(x));
}
+ DemanglerPrinter &writeHex(unsigned long long n) &;
+
std::string &&str() && { return std::move(Stream); }
llvm::StringRef getStringRef() const { return Stream; }
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index ed283d6..418435d 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -143,6 +143,7 @@
NODE(PrivateDeclName)
NODE(PropertyDescriptor)
CONTEXT_NODE(Protocol)
+CONTEXT_NODE(ProtocolSymbolicReference)
NODE(ProtocolConformance)
NODE(ProtocolDescriptor)
NODE(ProtocolConformanceDescriptor)
@@ -172,13 +173,13 @@
CONTEXT_NODE(Static)
CONTEXT_NODE(Structure)
CONTEXT_NODE(Subscript)
-CONTEXT_NODE(SymbolicReference)
NODE(Suffix)
NODE(ThinFunctionType)
NODE(Tuple)
NODE(TupleElement)
NODE(TupleElementName)
NODE(Type)
+CONTEXT_NODE(TypeSymbolicReference)
CONTEXT_NODE(TypeAlias)
NODE(TypeList)
NODE(TypeMangling)
@@ -192,7 +193,6 @@
NODE(UncurriedFunctionType)
#define REF_STORAGE(Name, ...) NODE(Name)
#include "swift/AST/ReferenceStorage.def"
-CONTEXT_NODE(UnresolvedSymbolicReference)
CONTEXT_NODE(UnsafeAddressor)
CONTEXT_NODE(UnsafeMutableAddressor)
NODE(ValueWitness)
diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h
index cbc309e..6651002 100644
--- a/include/swift/Demangling/Demangler.h
+++ b/include/swift/Demangling/Demangler.h
@@ -280,6 +280,17 @@
}
};
+/// Kinds of symbolic reference supported.
+enum class SymbolicReferenceKind : uint8_t {
+ /// A symbolic reference to a context descriptor, representing the
+ /// (unapplied generic) context.
+ Context,
+};
+
+using SymbolicReferenceResolver_t = NodePointer (SymbolicReferenceKind,
+ Directness,
+ int32_t, const void *);
+
/// The demangler.
///
/// It de-mangles a string and it also owns the returned node-tree. This means
@@ -301,7 +312,7 @@
StringRef Words[MaxNumWords];
int NumWords = 0;
- std::function<NodePointer (int32_t, const void *)> SymbolicReferenceResolver;
+ std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver;
bool nextIf(StringRef str) {
if (!Text.substr(Pos).startswith(str)) return false;
@@ -472,7 +483,8 @@
NodePointer demangleObjCTypeName();
NodePointer demangleTypeMangling();
- NodePointer demangleSymbolicReference(const void *at);
+ NodePointer demangleSymbolicReference(unsigned char rawKind,
+ const void *at);
void dump();
@@ -483,7 +495,7 @@
/// Install a resolver for symbolic references in a mangled string.
void setSymbolicReferenceResolver(
- std::function<NodePointer (int32_t, const void*)> resolver) {
+ std::function<SymbolicReferenceResolver_t> resolver) {
SymbolicReferenceResolver = resolver;
}
diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h
index 5f41b8f..6d847ad 100644
--- a/include/swift/Demangling/TypeDecoder.h
+++ b/include/swift/Demangling/TypeDecoder.h
@@ -114,7 +114,7 @@
case NodeKind::Enum:
case NodeKind::Structure:
case NodeKind::TypeAlias: // This can show up for imported Clang decls.
- case NodeKind::SymbolicReference:
+ case NodeKind::TypeSymbolicReference:
{
BuiltNominalTypeDecl typeDecl = BuiltNominalTypeDecl();
BuiltType parent = BuiltType();
@@ -228,7 +228,8 @@
IsClassBound);
}
- case NodeKind::Protocol: {
+ case NodeKind::Protocol:
+ case NodeKind::ProtocolSymbolicReference: {
if (auto Proto = decodeMangledProtocolType(Node)) {
return Builder.createProtocolCompositionType(Proto, BuiltType(),
/*IsClassBound=*/false);
@@ -473,14 +474,14 @@
}
private:
- bool decodeMangledNominalType(const Demangle::NodePointer &node,
+ bool decodeMangledNominalType(Demangle::NodePointer node,
BuiltNominalTypeDecl &typeDecl,
BuiltType &parent) {
if (node->getKind() == NodeKind::Type)
return decodeMangledNominalType(node->getChild(0), typeDecl, parent);
Demangle::NodePointer nominalNode;
- if (node->getKind() == NodeKind::SymbolicReference) {
+ if (node->getKind() == NodeKind::TypeSymbolicReference) {
// A symbolic reference can be directly resolved to a nominal type.
nominalNode = node;
} else {
@@ -519,19 +520,19 @@
return true;
}
- BuiltProtocolDecl decodeMangledProtocolType(
- const Demangle::NodePointer &node) {
+ BuiltProtocolDecl decodeMangledProtocolType(Demangle::NodePointer node) {
if (node->getKind() == NodeKind::Type)
return decodeMangledProtocolType(node->getChild(0));
- if (node->getNumChildren() < 2 || node->getKind() != NodeKind::Protocol)
+ if ((node->getNumChildren() < 2 || node->getKind() != NodeKind::Protocol)
+ && node->getKind() != NodeKind::ProtocolSymbolicReference)
return BuiltProtocolDecl();
return Builder.createProtocolDecl(node);
}
bool decodeMangledFunctionInputType(
- const Demangle::NodePointer &node,
+ Demangle::NodePointer node,
std::vector<FunctionParam<BuiltType>> ¶ms,
bool &hasParamFlags) {
// Look through a couple of sugar nodes.
@@ -542,7 +543,7 @@
}
auto decodeParamTypeAndFlags =
- [&](const Demangle::NodePointer &typeNode,
+ [&](Demangle::NodePointer typeNode,
FunctionParam<BuiltType> ¶m) -> bool {
Demangle::NodePointer node = typeNode;
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 1991df6..d995632 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -32,6 +32,7 @@
namespace swift {
namespace irgen {
class IRGenModule;
+class Alignment;
/// Determine if the triple uses the DLL storage.
bool useDllStorage(const llvm::Triple &triple);
@@ -936,6 +937,17 @@
return getDecl()->isWeakImported(module);
}
+
+ /// Return the source file whose codegen should trigger emission of this
+ /// link entity, if one can be identified.
+ const SourceFile *getSourceFileForEmission() const;
+
+ /// Get the preferred alignment for the definition of this entity.
+ Alignment getAlignment(IRGenModule &IGM) const;
+
+ /// Get the default LLVM type to use for forward declarations of this
+ /// entity.
+ llvm::Type *getDefaultDeclarationType(IRGenModule &IGM) const;
#undef LINKENTITY_GET_FIELD
#undef LINKENTITY_SET_FIELD
};
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index 921b925..8574a22 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -354,15 +354,30 @@
// demangling out of the referenced context descriptors in the target
// process.
Dem.setSymbolicReferenceResolver(
- [this, &reader](int32_t offset, const void *base) -> Demangle::NodePointer {
- // Resolve the reference to a remote address.
- auto remoteAddress = getRemoteAddrOfTypeRefPointer(base);
- if (remoteAddress == 0)
+ [this, &reader](SymbolicReferenceKind kind,
+ Directness directness,
+ int32_t offset, const void *base) -> Demangle::NodePointer {
+ // Resolve the reference to a remote address.
+ auto remoteAddress = getRemoteAddrOfTypeRefPointer(base);
+ if (remoteAddress == 0)
+ return nullptr;
+
+ auto address = remoteAddress + offset;
+ if (directness == Directness::Indirect) {
+ if (auto indirectAddress = reader.readPointerValue(address)) {
+ address = *indirectAddress;
+ } else {
return nullptr;
-
- return reader.readDemanglingForContextDescriptor(remoteAddress + offset,
- Dem);
- });
+ }
+ }
+
+ switch (kind) {
+ case Demangle::SymbolicReferenceKind::Context:
+ return reader.readDemanglingForContextDescriptor(address, Dem);
+ }
+
+ return nullptr;
+ });
}
TypeConverter &getTypeConverter() { return TC; }
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index f87dd42..c271635 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -573,8 +573,8 @@
// Build the demangling tree from the context tree.
Demangle::NodeFactory nodeFactory;
- auto node = buildNominalTypeMangling(descriptor, nodeFactory);
- if (!node)
+ auto node = buildContextMangling(descriptor, nodeFactory);
+ if (!node || node->getKind() != Node::Kind::Type)
return BuiltType();
auto name = Demangle::mangleNode(node);
@@ -614,7 +614,7 @@
auto context = readContextDescriptor(contextAddress);
if (!context)
return nullptr;
- return buildNominalTypeMangling(context, Dem);
+ return buildContextMangling(context, Dem);
}
/// Read the isa pointer of a class or closure context instance and apply
@@ -1244,7 +1244,7 @@
metadataInitSize = readMetadataInitSize();
break;
case ContextDescriptorKind::Protocol:
- baseSize = sizeof(TargetProtocolDescriptorRef<Runtime>);
+ baseSize = sizeof(TargetProtocolDescriptor<Runtime>);
break;
default:
// We don't know about this kind of context.
@@ -1427,9 +1427,21 @@
// 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::Anonymous: {
+ // Use the remote address to identify the anonymous context.
+ char addressBuf[18];
+ snprintf(addressBuf, sizeof(addressBuf), "$%" PRIx64,
+ (uint64_t)descriptor.getAddress());
+ auto anonNode = nodeFactory.createNode(Node::Kind::AnonymousContext);
+ CharVector addressStr;
+ addressStr.append(addressBuf, nodeFactory);
+ auto name = nodeFactory.createNode(Node::Kind::Identifier, addressStr);
+ anonNode->addChild(name, nodeFactory);
+ if (parentDemangling)
+ anonNode->addChild(parentDemangling, nodeFactory);
+
+ return anonNode;
+ }
case ContextDescriptorKind::Module: {
// Modules shouldn't have a parent.
@@ -1481,6 +1493,18 @@
auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
std::move(nodeName));
+
+ // Use private declaration names for anonymous context references.
+ if (parentDemangling->getKind() == Node::Kind::AnonymousContext) {
+ auto privateDeclName =
+ nodeFactory.createNode(Node::Kind::PrivateDeclName);
+ privateDeclName->addChild(parentDemangling->getChild(0), nodeFactory);
+ privateDeclName->addChild(nameNode, nodeFactory);
+
+ nameNode = privateDeclName;
+ parentDemangling = parentDemangling->getChild(1);
+ }
+
if (importInfo && !importInfo->RelatedEntityName.empty()) {
auto relatedNode =
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName,
@@ -1495,17 +1519,25 @@
return demangling;
}
- /// Given a read nominal type descriptor, attempt to build a demangling tree
+ /// Given a read context descriptor, attempt to build a demangling tree
/// for it.
Demangle::NodePointer
- buildNominalTypeMangling(ContextDescriptorRef descriptor,
- Demangle::NodeFactory &nodeFactory) {
+ buildContextMangling(ContextDescriptorRef descriptor,
+ Demangle::NodeFactory &nodeFactory) {
auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
if (!demangling)
return nullptr;
- auto top = nodeFactory.createNode(Node::Kind::Type);
- top->addChild(demangling, nodeFactory);
+ NodePointer top;
+ // References to type nodes behave as types in the mangling.
+ if (isa<TargetTypeContextDescriptor<Runtime>>(descriptor.getLocalBuffer()) ||
+ isa<TargetProtocolDescriptor<Runtime>>(descriptor.getLocalBuffer())) {
+ top = nodeFactory.createNode(Node::Kind::Type);
+ top->addChild(demangling, nodeFactory);
+ } else {
+ top = demangling;
+ }
+
return top;
}
@@ -1515,8 +1547,8 @@
buildNominalTypeDecl(ContextDescriptorRef descriptor) {
// Build the demangling tree from the context tree.
Demangle::NodeFactory nodeFactory;
- auto node = buildNominalTypeMangling(descriptor, nodeFactory);
- if (!node)
+ auto node = buildContextMangling(descriptor, nodeFactory);
+ if (!node || node->getKind() != Node::Kind::Type)
return BuiltNominalTypeDecl();
BuiltNominalTypeDecl decl = Builder.createNominalTypeDecl(node);
return decl;
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index a92a97b..0b58ffb 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -462,7 +462,7 @@
assert(Root->getKind() == Node::Kind::Global);
Node *NomTy = Root->getFirstChild();
if (NomTy->getKind() == Node::Kind::Protocol) {
- // Protocols are actually mangled as protocol lists.
+ // Protocol types are mangled as protocol lists.
Node *PTy = Dem.createNode(Node::Kind::Type);
PTy->addChild(NomTy, Dem);
Node *TList = Dem.createNode(Node::Kind::TypeList);
@@ -1499,6 +1499,19 @@
if (allowStandardSubstitution && tryAppendStandardSubstitution(protocol))
return;
+ // We can use a symbolic reference if they're allowed in this context.
+ if (AllowSymbolicReferences
+ && (!CanSymbolicReference || CanSymbolicReference(protocol))) {
+ // Try to use a symbolic reference substitution.
+ if (tryMangleSubstitution(protocol))
+ return;
+
+ appendSymbolicReference(protocol);
+ // Substitutions can refer back to the symbolic reference.
+ addSubstitution(protocol);
+ return;
+ }
+
appendContextOf(protocol);
auto *clangDecl = protocol->getClangDecl();
if (auto *clangProto = cast_or_null<clang::ObjCProtocolDecl>(clangDecl))
@@ -1525,13 +1538,12 @@
return namedDecl;
}
-void ASTMangler::appendSymbolicReference(const DeclContext *context) {
+void ASTMangler::appendSymbolicReference(SymbolicReferent referent) {
// Drop in a placeholder. The real reference value has to be filled in during
// lowering to IR.
- Buffer << '\1';
auto offset = Buffer.str().size();
- Buffer << StringRef("\0\0\0\0", 4);
- SymbolicReferences.emplace_back(context, offset);
+ Buffer << StringRef("\0\0\0\0\0", 5);
+ SymbolicReferences.emplace_back(referent, offset);
}
void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
@@ -1554,13 +1566,16 @@
if (tryMangleSubstitution(key.getPointer()))
return;
- // Try to mangle a symbolic reference.
- if (CanSymbolicReference
- && CanSymbolicReference(key->getAnyNominal())) {
- appendSymbolicReference(key->getAnyNominal());
- // Substitutions can refer back to the symbolic reference.
- addSubstitution(key.getPointer());
- return;
+ // Try to mangle a symbolic reference for a nominal type.
+ if (AllowSymbolicReferences) {
+ auto nominal = key->getAnyNominal();
+ if (nominal && !isa<ProtocolDecl>(nominal)
+ && (!CanSymbolicReference || CanSymbolicReference(nominal))) {
+ appendSymbolicReference(nominal);
+ // Substitutions can refer back to the symbolic reference.
+ addSubstitution(key.getPointer());
+ return;
+ }
}
appendContextOf(decl);
@@ -2183,7 +2198,8 @@
appendOperator("Z");
}
-void ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance){
+void
+ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance) {
GenericSignature *contextSig = nullptr;
auto topLevelContext =
conformance->getDeclContext()->getModuleScopeContext();
@@ -2199,6 +2215,7 @@
} else {
auto conformingType = conformance->getType();
appendType(conformingType->getCanonicalType());
+
appendProtocolName(conformance->getProtocol());
bool needsModule = true;
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index f874234..8654bf6 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -39,8 +39,8 @@
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
case Node::Kind::InfixOperator:
- case Node::Kind::UnresolvedSymbolicReference:
- case Node::Kind::SymbolicReference:
+ case Node::Kind::TypeSymbolicReference:
+ case Node::Kind::ProtocolSymbolicReference:
return true;
default:
return false;
@@ -65,10 +65,10 @@
case Node::Kind::Class:
case Node::Kind::Enum:
case Node::Kind::Protocol:
+ case Node::Kind::ProtocolSymbolicReference:
case Node::Kind::OtherNominalType:
case Node::Kind::TypeAlias:
- case Node::Kind::SymbolicReference:
- case Node::Kind::UnresolvedSymbolicReference:
+ case Node::Kind::TypeSymbolicReference:
return true;
default:
return false;
@@ -241,6 +241,7 @@
case Demangle::Node::Kind::Type:
return isProtocolNode(Node->getChild(0));
case Demangle::Node::Kind::Protocol:
+ case Demangle::Node::Kind::ProtocolSymbolicReference:
return true;
default:
return false;
@@ -547,31 +548,52 @@
return TypeMangling;
}
-NodePointer Demangler::demangleSymbolicReference(const void *at) {
+NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind,
+ const void *at) {
// The symbolic reference is a 4-byte machine integer encoded in the following
// four bytes.
int32_t value;
memcpy(&value, Text.data() + Pos, 4);
Pos += 4;
+ // Map the encoded kind to a specific kind and directness.
+ SymbolicReferenceKind kind;
+ Directness direct;
+ switch (rawKind) {
+ case 1:
+ kind = SymbolicReferenceKind::Context;
+ direct = Directness::Direct;
+ break;
+ case 2:
+ kind = SymbolicReferenceKind::Context;
+ direct = Directness::Indirect;
+ break;
+ default:
+ return nullptr;
+ }
+
// Use the resolver, if any, to produce the demangling tree the symbolic
// reference represents.
NodePointer resolved = nullptr;
if (SymbolicReferenceResolver)
- resolved = SymbolicReferenceResolver(value, at);
- // With no resolver, or a resolver that failed, simply preserve the raw
- // information in the node.
+ resolved = SymbolicReferenceResolver(kind, direct, value, at);
+ // With no resolver, or a resolver that failed, refuse to demangle further.
if (!resolved)
- resolved = createNode(Node::Kind::UnresolvedSymbolicReference, value);
+ return nullptr;
- // Register the result as a substitution.
- addSubstitution(resolved);
+ // Types register as substitutions even when symbolically referenced.
+ if (kind == SymbolicReferenceKind::Context)
+ addSubstitution(resolved);
return resolved;
}
NodePointer Demangler::demangleOperator() {
switch (char c = nextChar()) {
- case '\1': return demangleSymbolicReference(Text.data() + Pos);
+ case '\1':
+ case '\2':
+ case '\3':
+ case '\4':
+ return demangleSymbolicReference((unsigned char)c, Text.data() + Pos);
case 'A': return demangleMultiSubstitutions();
case 'B': return demangleBuiltinType();
case 'C': return demangleAnyGenericType(Node::Kind::Class);
@@ -1204,12 +1226,15 @@
if (Type->getNumChildren() < 1)
return nullptr;
- NodePointer Proto = Type->getChild(0);
- if (Proto->getKind() != Node::Kind::Protocol)
+ if (!isProtocolNode(Type))
return nullptr;
return Type;
}
+
+ if (NodePointer SymbolicRef = popNode(Node::Kind::ProtocolSymbolicReference)){
+ return SymbolicRef;
+ }
NodePointer Name = popNode(isDeclName);
NodePointer Ctx = popContext();
@@ -1273,9 +1298,10 @@
if (TypeListIdx >= TypeLists.size())
return nullptr;
- // Associate a symbolic reference with all remaining generic arguments.
- if (Nominal->getKind() == Node::Kind::SymbolicReference
- || Nominal->getKind() == Node::Kind::UnresolvedSymbolicReference) {
+ // Associate a context symbolic reference with all remaining generic
+ // arguments.
+ if (Nominal->getKind() == Node::Kind::TypeSymbolicReference
+ || Nominal->getKind() == Node::Kind::ProtocolSymbolicReference) {
auto remainingTypeList = createNode(Node::Kind::TypeList);
for (unsigned i = TypeLists.size() - 1;
i >= TypeListIdx && i < TypeLists.size();
@@ -1349,30 +1375,30 @@
Node::Kind kind;
switch (Nominal->getKind()) {
- case Node::Kind::Class:
- kind = Node::Kind::BoundGenericClass;
- break;
- case Node::Kind::Structure:
- kind = Node::Kind::BoundGenericStructure;
- break;
- case Node::Kind::Enum:
- kind = Node::Kind::BoundGenericEnum;
- break;
- case Node::Kind::Protocol:
- kind = Node::Kind::BoundGenericProtocol;
- break;
- case Node::Kind::OtherNominalType:
- kind = Node::Kind::BoundGenericOtherNominalType;
- break;
- case Node::Kind::TypeAlias:
- kind = Node::Kind::BoundGenericTypeAlias;
- break;
- case Node::Kind::Function:
- case Node::Kind::Constructor:
- // Well, not really a nominal type.
- return createWithChildren(Node::Kind::BoundGenericFunction, Nominal, args);
- default:
- return nullptr;
+ case Node::Kind::Class:
+ kind = Node::Kind::BoundGenericClass;
+ break;
+ case Node::Kind::Structure:
+ kind = Node::Kind::BoundGenericStructure;
+ break;
+ case Node::Kind::Enum:
+ kind = Node::Kind::BoundGenericEnum;
+ break;
+ case Node::Kind::Protocol:
+ kind = Node::Kind::BoundGenericProtocol;
+ break;
+ case Node::Kind::OtherNominalType:
+ kind = Node::Kind::BoundGenericOtherNominalType;
+ break;
+ case Node::Kind::TypeAlias:
+ kind = Node::Kind::BoundGenericTypeAlias;
+ break;
+ case Node::Kind::Function:
+ case Node::Kind::Constructor:
+ // Well, not really a nominal type.
+ return createWithChildren(Node::Kind::BoundGenericFunction, Nominal, args);
+ default:
+ return nullptr;
}
return createWithChildren(kind, createType(Nominal), args);
}
@@ -1655,7 +1681,7 @@
NodePointer Demangler::popAssocTypeName() {
NodePointer Proto = popNode(Node::Kind::Type);
- if (Proto && Proto->getFirstChild()->getKind() != Node::Kind::Protocol)
+ if (Proto && !isProtocolNode(Proto))
return nullptr;
NodePointer Id = popNode(Node::Kind::Identifier);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 363d552..d9228b1 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -37,6 +37,12 @@
Stream.append(buffer);
return *this;
}
+DemanglerPrinter &DemanglerPrinter::writeHex(unsigned long long n) & {
+ char buffer[32];
+ snprintf(buffer, sizeof(buffer), "%llX", n);
+ Stream.append(buffer);
+ return *this;
+}
DemanglerPrinter &DemanglerPrinter::operator<<(long long n) & {
char buffer[32];
snprintf(buffer, sizeof(buffer), "%lld",n);
@@ -285,6 +291,7 @@
case Node::Kind::Module:
case Node::Kind::Tuple:
case Node::Kind::Protocol:
+ case Node::Kind::ProtocolSymbolicReference:
case Node::Kind::ReturnType:
case Node::Kind::SILBoxType:
case Node::Kind::SILBoxTypeWithLayout:
@@ -295,8 +302,7 @@
case Node::Kind::TypeAlias:
case Node::Kind::TypeList:
case Node::Kind::LabelList:
- case Node::Kind::SymbolicReference:
- case Node::Kind::UnresolvedSymbolicReference:
+ case Node::Kind::TypeSymbolicReference:
return true;
case Node::Kind::ProtocolList:
@@ -1499,11 +1505,13 @@
Printer << "merged ";
}
return nullptr;
- case Node::Kind::SymbolicReference:
- Printer << "symbolic reference " << Node->getIndex();
+ case Node::Kind::TypeSymbolicReference:
+ Printer << "type symbolic reference 0x";
+ Printer.writeHex(Node->getIndex());
return nullptr;
- case Node::Kind::UnresolvedSymbolicReference:
- Printer << "$" << Node->getIndex();
+ case Node::Kind::ProtocolSymbolicReference:
+ Printer << "protocol symbolic reference 0x";
+ Printer.writeHex(Node->getIndex());
return nullptr;
case Node::Kind::GenericTypeMetadataPattern:
Printer << "generic type metadata pattern for ";
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index e4f08ee..ebb2c27 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -2156,11 +2156,11 @@
unreachable("unsupported");
}
-void Remangler::mangleUnresolvedSymbolicReference(Node *node, EntityContext&) {
+void Remangler::mangleTypeSymbolicReference(Node *node, EntityContext&) {
unreachable("unsupported");
}
-void Remangler::mangleSymbolicReference(Node *node, EntityContext&) {
+void Remangler::mangleProtocolSymbolicReference(Node *node, EntityContext&) {
unreachable("unsupported");
}
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 348b288..f497f90 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -948,7 +948,8 @@
void Remangler::mangleAnonymousContext(Node *node) {
mangleChildNode(node, 1);
mangleChildNode(node, 0);
- mangleTypeList(node->getChild(2));
+ if (node->getNumChildren() >= 3)
+ mangleTypeList(node->getChild(2));
Buffer << "XZ";
}
@@ -2115,23 +2116,21 @@
Buffer << "MXA";
}
-void Remangler::mangleUnresolvedSymbolicReference(Node *node) {
- Buffer << "$";
- char bytes[4];
- uint32_t value = node->getIndex();
- memcpy(bytes, &value, 4);
- Buffer << StringRef(bytes, 4);
+void Remangler::mangleTypeSymbolicReference(Node *node) {
+ return mangle(Resolver(SymbolicReferenceKind::Context,
+ (const void *)node->getIndex()));
}
-void Remangler::mangleSymbolicReference(Node *node) {
- return mangle(Resolver((const void *)node->getIndex()));
+void Remangler::mangleProtocolSymbolicReference(Node *node) {
+ return mangle(Resolver(SymbolicReferenceKind::Context,
+ (const void *)node->getIndex()));
}
} // anonymous namespace
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(const NodePointer &node) {
- return mangleNode(node, [](const void *) -> NodePointer {
+ return mangleNode(node, [](SymbolicReferenceKind, const void *) -> NodePointer {
unreachable("should not try to mangle a symbolic reference; "
"resolve it to a non-symbolic demangling tree instead");
});
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 26b4476..c7af260 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -801,10 +801,9 @@
? ConstantReference::Indirect
: ConstantReference::Direct;
+ IRGen.noteUseOfTypeContextDescriptor(nominal, DontRequireMetadata);
return getAddrOfLLVMVariableOrGOTEquivalent(
LinkEntity::forNominalTypeDescriptor(nominal),
- Alignment(4),
- TypeContextDescriptorTy,
shouldBeIndirect);
}
}
@@ -868,9 +867,7 @@
// Try to form a direct reference to the nominal type descriptor if it's in
// the same binary, or use the GOT entry if it's from another binary.
return getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forProtocolDescriptor(proto),
- getPointerAlignment(),
- ProtocolDescriptorStructTy);
+ LinkEntity::forProtocolDescriptor(proto));
}
llvm::Constant *IRGenModule::getAddrOfAssociatedTypeGenericParamRef(
@@ -911,8 +908,7 @@
// Add a reference to the associated type descriptor.
auto assocTypeDescriptor =
getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forAssociatedTypeDescriptor(assocType),
- Alignment(4), ProtocolRequirementStructTy);
+ LinkEntity::forAssociatedTypeDescriptor(assocType));
B.addRelativeAddress(assocTypeDescriptor);
}
@@ -1228,10 +1224,13 @@
void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
bool isUseOfMetadata,
RequireMetadata_t requireMetadata) {
+ if (!type)
+ return;
+
// Try to create a new record of the fact that we used this type.
auto insertResult = LazyTypeGlobals.try_emplace(type);
auto &entry = insertResult.first->second;
-
+
bool metadataWasUsed = entry.IsMetadataUsed;
bool descriptorWasUsed = entry.IsDescriptorUsed;
@@ -2053,11 +2052,11 @@
/// result to emitRelativeReference, passing the correct base-address
/// information.
ConstantReference
-IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
+IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
ConstantInit definition,
- llvm::Type *defaultType,
DebugTypeInfo debugType,
- SymbolReferenceKind refKind) {
+ SymbolReferenceKind refKind,
+ llvm::Type *overrideDeclType) {
switch (refKind) {
case SymbolReferenceKind::Relative_Direct:
case SymbolReferenceKind::Far_Relative_Direct:
@@ -2067,15 +2066,15 @@
LLVM_FALLTHROUGH;
case SymbolReferenceKind::Absolute:
- return { getAddrOfLLVMVariable(entity, alignment, definition,
- defaultType, debugType),
+ return { getAddrOfLLVMVariable(entity, definition, debugType,
+ overrideDeclType),
ConstantReference::Direct };
case SymbolReferenceKind::Relative_Indirectable:
case SymbolReferenceKind::Far_Relative_Indirectable:
assert(!definition);
- return getAddrOfLLVMVariableOrGOTEquivalent(entity, alignment, defaultType);
+ return getAddrOfLLVMVariableOrGOTEquivalent(entity);
}
llvm_unreachable("bad reference kind");
}
@@ -2083,14 +2082,13 @@
/// A convenient wrapper around getAddrOfLLVMVariable which uses the
/// default type as the definition type.
llvm::Constant *
-IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
+IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
ForDefinition_t forDefinition,
- llvm::Type *defaultType,
DebugTypeInfo debugType) {
- auto definition =
- (forDefinition ? ConstantInit::getDelayed(defaultType) : ConstantInit());
- return getAddrOfLLVMVariable(entity, alignment, definition,
- defaultType, debugType);
+ auto definition = forDefinition
+ ? ConstantInit::getDelayed(entity.getDefaultDeclarationType(*this))
+ : ConstantInit();
+ return getAddrOfLLVMVariable(entity, definition, debugType);
}
/// Get or create an llvm::GlobalVariable.
@@ -2099,15 +2097,18 @@
/// llvm::GlobalVariable of that type. Otherwise, the result will
/// have type pointerToDefaultType and may involve bitcasts.
llvm::Constant *
-IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
+IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
ConstantInit definition,
- llvm::Type *defaultType,
- DebugTypeInfo DbgTy) {
+ DebugTypeInfo DbgTy,
+ llvm::Type *overrideDeclType) {
// This function assumes that 'globals' only contains GlobalValue
// values for the entities that it will look up.
llvm::Type *definitionType = (definition ? definition.getType() : nullptr);
-
+ auto defaultType = overrideDeclType
+ ? overrideDeclType
+ : entity.getDefaultDeclarationType(*this);
+
auto &entry = GlobalVars[entity];
if (entry) {
auto existing = cast<llvm::GlobalValue>(entry);
@@ -2151,7 +2152,8 @@
if (!definitionType) definitionType = defaultType;
// Create the variable.
- auto var = createVariable(*this, link, definitionType, alignment, DbgTy);
+ auto var = createVariable(*this, link, definitionType,
+ entity.getAlignment(*this), DbgTy);
// Install the concrete definition if we have one.
if (definition && definition.hasInit()) {
@@ -2196,8 +2198,6 @@
/// relative references to the GOT entry for the variable in the object file.
ConstantReference
IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
- Alignment alignment,
- llvm::Type *defaultType,
ConstantReference::Directness forceIndirectness) {
// ObjC class references can always be directly referenced, even in
// the weird cases where we don't see a definition.
@@ -2214,8 +2214,7 @@
= getAddrOfForeignTypeMetadataCandidate(entity.getType());
(void)foreignCandidate;
} else {
- getAddrOfLLVMVariable(entity, alignment, ConstantInit(),
- defaultType, DebugTypeInfo());
+ getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}
// Guess whether a global entry is a definition from this TU. This isn't
@@ -2232,44 +2231,70 @@
// Assume anything else isn't a definition.
return false;
};
-
- // If the variable has already been defined in this TU,
- // then it definitely doesn't need a GOT entry, and we can
- // relative-reference it directly.
+
//
- // TODO: If we know the target entry is going to be linked into the same
- // binary, then we ought to be able to directly relative-reference the
- // symbol. However, some platforms don't have the necessary relocations to
- // represent a relative reference to an undefined symbol, so conservatively
- // produce an indirect reference in this case. Also, the integrated REPL
- // incrementally adds new definitions that refer back to existing ones
- // relatively, so always use indirect references in this situation.
auto entry = GlobalVars[entity];
- if (forceIndirectness == ConstantReference::Direct &&
- !IRGen.Opts.IntegratedREPL &&
- (!entity.isAvailableExternally(*this) || isDefinition(entry))) {
+
+ /// Returns a direct reference.
+ auto direct = [&]() -> ConstantReference {
// FIXME: Relative references to aliases break MC on 32-bit Mach-O
// platforms (rdar://problem/22450593 ), so substitute an alias with its
// aliasee to work around that.
if (auto alias = dyn_cast<llvm::GlobalAlias>(entry))
- entry = alias->getAliasee();
+ return {alias->getAliasee(), ConstantReference::Direct};
return {entry, ConstantReference::Direct};
+ };
+
+ /// Returns an indirect reference.
+ auto indirect = [&]() -> ConstantReference {
+ auto &gotEntry = GlobalGOTEquivalents[entity];
+ if (gotEntry) {
+ return {gotEntry, ConstantReference::Indirect};
+ }
+
+ // Look up the global variable.
+ auto global = cast<llvm::GlobalValue>(entry);
+ // Use it as the initializer for an anonymous constant. LLVM can treat this as
+ // equivalent to the global's GOT entry.
+ llvm::SmallString<64> name;
+ entity.mangle(name);
+ auto gotEquivalent = createGOTEquivalent(*this, global, name);
+ gotEntry = gotEquivalent;
+ return {gotEquivalent, ConstantReference::Indirect};
+ };
+
+ // Return the GOT entry if we were asked to.
+ if (forceIndirectness == ConstantReference::Indirect)
+ return indirect();
+
+ // The integrated REPL incrementally adds new definitions, so always use
+ // indirect references in this mode.
+ if (IRGen.Opts.IntegratedREPL)
+ return indirect();
+
+ // If the variable has already been defined in this TU,
+ // then it definitely doesn't need a GOT entry, and we can
+ // relative-reference it directly.
+ if ((!entity.isAvailableExternally(*this) || isDefinition(entry))) {
+ return direct();
}
- auto &gotEntry = GlobalGOTEquivalents[entity];
- if (gotEntry) {
- return {gotEntry, ConstantReference::Indirect};
- }
+ // If the entity will be emitted as part of the current source file
+ // (if we know what that is), then we can reference it directly.
+ if (CurSourceFile
+ && !isa<ClangModuleUnit>(CurSourceFile)
+ && CurSourceFile == entity.getSourceFileForEmission())
+ return direct();
+
+ // TODO: If we know the target entry is going to be linked into the same
+ // binary, then we ought to be able to directly relative-reference the
+ // symbol. However, some platforms don't have the necessary relocations to
+ // represent a relative reference to an undefined symbol, so conservatively
+ // produce an indirect reference in this case.
- // Look up the global variable.
- auto global = cast<llvm::GlobalValue>(entry);
- // Use it as the initializer for an anonymous constant. LLVM can treat this as
- // equivalent to the global's GOT entry.
- llvm::SmallString<64> name;
- entity.mangle(name);
- auto gotEquivalent = createGOTEquivalent(*this, global, name);
- gotEntry = gotEquivalent;
- return {gotEquivalent, ConstantReference::Indirect};
+ // Fall back to an indirect reference if we can't establish that a direct
+ // reference is OK.
+ return indirect();
}
static TypeEntityReference
@@ -2280,10 +2305,9 @@
// to be looked up dynamically) for types defined outside the module.
auto kind = TypeReferenceKind::DirectNominalTypeDescriptor;
auto entity = LinkEntity::forNominalTypeDescriptor(decl);
- auto defaultTy = IGM.TypeContextDescriptorTy;
- auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- entity, IGM.getPointerAlignment(), defaultTy);
+ IGM.IRGen.noteUseOfTypeContextDescriptor(decl, DontRequireMetadata);
+ auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(entity);
if (ref.isIndirect()) {
kind = TypeReferenceKind::IndirectNominalTypeDescriptor;
@@ -2299,10 +2323,8 @@
auto kind = TypeReferenceKind::IndirectObjCClass;
auto entity = LinkEntity::forObjCClassRef(cls);
- auto defaultTy = IGM.TypeMetadataPtrTy;
- auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- entity, IGM.getPointerAlignment(), defaultTy);
+ auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(entity);
assert(!ref.isIndirect());
return TypeEntityReference(kind, ref.getValue());
@@ -2413,8 +2435,7 @@
// Relative reference to the protocol descriptor.
auto descriptorRef = getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forProtocolDescriptor(protocol),
- getPointerAlignment(), ProtocolDescriptorStructTy);
+ LinkEntity::forProtocolDescriptor(protocol));
record.addRelativeAddress(descriptorRef);
record.finishAndAddTo(recordsArray);
@@ -2489,8 +2510,7 @@
auto entity = LinkEntity::forProtocolConformanceDescriptor(conformance);
auto descriptor =
- getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(),
- ProtocolConformanceDescriptorTy, DebugTypeInfo());
+ getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
descriptorArray.addRelativeAddress(descriptor);
}
@@ -2568,7 +2588,7 @@
for (auto type : RuntimeResolvableTypes) {
auto ref = getTypeEntityReference(type);
- // Form the relative address, with the type refernce kind in the low bits.
+ // Form the relative address, with the type reference kind in the low bits.
unsigned arrayIdx = elts.size();
llvm::Constant *relativeAddr =
emitDirectRelativeReference(ref.getValue(), var, { arrayIdx, 0 });
@@ -2650,13 +2670,10 @@
Address IRGenModule::getAddrOfObjCClassRef(ClassDecl *theClass) {
assert(ObjCInterop && "getting address of ObjC class ref in no-interop mode");
- Alignment alignment = getPointerAlignment();
-
LinkEntity entity = LinkEntity::forObjCClassRef(theClass);
auto DbgTy = DebugTypeInfo::getObjCClass(
theClass, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
- auto addr = getAddrOfLLVMVariable(entity, alignment, ConstantInit(),
- ObjCClassPtrTy, DbgTy);
+ auto addr = getAddrOfLLVMVariable(entity, ConstantInit(), DbgTy);
// Define it lazily.
if (auto global = dyn_cast<llvm::GlobalVariable>(addr)) {
@@ -2670,7 +2687,7 @@
}
}
- return Address(addr, alignment);
+ return Address(addr, entity.getAlignment(*this));
}
/// Fetch a global reference to the given Objective-C class. The
@@ -2682,8 +2699,7 @@
LinkEntity entity = LinkEntity::forObjCClass(theClass);
auto DbgTy = DebugTypeInfo::getObjCClass(
theClass, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
- auto addr = getAddrOfLLVMVariable(entity, getPointerAlignment(),
- forDefinition, ObjCClassStructTy, DbgTy);
+ auto addr = getAddrOfLLVMVariable(entity, forDefinition, DbgTy);
return addr;
}
@@ -2703,8 +2719,7 @@
auto DbgTy = DebugTypeInfo::getObjCClass(
decl, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
- auto addr = getAddrOfLLVMVariable(entity, getPointerAlignment(),
- forDefinition, ObjCClassStructTy, DbgTy);
+ auto addr = getAddrOfLLVMVariable(entity, forDefinition, DbgTy);
return addr;
}
@@ -2785,8 +2800,7 @@
assert(!type->hasArchetype() && !type->hasTypeParameter());
LinkEntity entity = LinkEntity::forTypeMetadataLazyCacheVariable(type);
auto variable =
- getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
- TypeMetadataPtrTy, DebugTypeInfo());
+ getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
// Zero-initialize if we're asking for a definition.
if (forDefinition) {
@@ -2801,25 +2815,14 @@
IRGenModule::getAddrOfTypeMetadataSingletonInitializationCache(
NominalTypeDecl *D,
ForDefinition_t forDefinition) {
- // Build the cache type.
- llvm::Type *cacheTy;
- if (isa<StructDecl>(D) || isa<EnumDecl>(D) || isa<ClassDecl>(D)) {
- // This is struct SingletonMetadataCache.
- cacheTy = llvm::StructType::get(getLLVMContext(),
- {TypeMetadataPtrTy, Int8PtrTy});
- } else {
- llvm_unreachable("in-place initialization for classes not yet supported");
- }
-
auto entity = LinkEntity::forTypeMetadataSingletonInitializationCache(D);
auto variable =
- getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
- cacheTy, DebugTypeInfo());
+ getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
// Zero-initialize if we're asking for a definition.
if (forDefinition) {
cast<llvm::GlobalVariable>(variable)->setInitializer(
- llvm::Constant::getNullValue(cacheTy));
+ llvm::Constant::getNullValue(variable->getType()->getPointerElementType()));
}
return variable;
@@ -2890,29 +2893,25 @@
/// For concrete metadata, we want to use the initializer on the
/// "full metadata", and define the "direct" address point as an alias.
TypeMetadataAddress addrKind;
- llvm::Type *defaultVarTy;
unsigned adjustmentIndex;
- Alignment alignment = getPointerAlignment();
if (concreteType->getClassOrBoundGenericClass()) {
addrKind = TypeMetadataAddress::FullMetadata;
- defaultVarTy = FullHeapMetadataStructTy;
adjustmentIndex = MetadataAdjustmentIndex::Class;
} else {
addrKind = TypeMetadataAddress::FullMetadata;
- defaultVarTy = FullTypeMetadataStructTy;
adjustmentIndex = MetadataAdjustmentIndex::ValueType;
}
auto entity = LinkEntity::forTypeMetadata(concreteType, addrKind);
auto DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
- defaultVarTy->getPointerTo(), Size(0),
- Alignment(1));
+ entity.getDefaultDeclarationType(*this)->getPointerTo(),
+ Size(0), Alignment(1));
// Define the variable.
llvm::GlobalVariable *var = cast<llvm::GlobalVariable>(
- getAddrOfLLVMVariable(entity, alignment, init, defaultVarTy, DbgTy));
+ getAddrOfLLVMVariable(entity, init, DbgTy));
var->setConstant(isConstant);
if (!section.empty())
@@ -2928,7 +2927,7 @@
// For concrete metadata, declare the alias to its address point.
auto directEntity = LinkEntity::forTypeMetadata(concreteType,
- TypeMetadataAddress::AddressPoint);
+ TypeMetadataAddress::AddressPoint);
llvm::Constant *addr = var;
// Do an adjustment if necessary.
@@ -2970,7 +2969,6 @@
llvm::Type *defaultVarTy;
unsigned adjustmentIndex;
- Alignment alignment = getPointerAlignment();
ClassDecl *ObjCClass = nullptr;
@@ -3025,8 +3023,8 @@
defaultVarTy->getPointerTo(), Size(0),
Alignment(1));
- auto addr = getAddrOfLLVMVariable(entity, alignment, ConstantInit(),
- defaultVarTy, DbgTy, refKind);
+ auto addr = getAddrOfLLVMVariable(entity, ConstantInit(), DbgTy, refKind,
+ defaultVarTy);
// FIXME: MC breaks when emitting alias references on some platforms
// (rdar://problem/22450593 ). Work around this by referring to the aliasee
@@ -3061,10 +3059,8 @@
if (!init)
IRGen.noteUseOfTypeMetadata(D);
- auto alignment = getPointerAlignment();
LinkEntity entity = LinkEntity::forTypeMetadataPattern(D);
- auto addr = getAddrOfLLVMVariable(entity, alignment, init,
- Int8Ty, DebugTypeInfo());
+ auto addr = getAddrOfLLVMVariable(entity, init, DebugTypeInfo());
if (init) {
auto var = cast<llvm::GlobalVariable>(addr);
@@ -3083,16 +3079,8 @@
llvm::Constant *
IRGenModule::getAddrOfClassMetadataBounds(ClassDecl *D,
ForDefinition_t forDefinition) {
- // StoredClassMetadataBounds
- auto layoutTy = llvm::StructType::get(getLLVMContext(), {
- SizeTy, // Immediate members offset
- Int32Ty, // Negative size in words
- Int32Ty // Positive size in words
- });
-
LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
- layoutTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}
/// Return the address of a generic type's metadata instantiation cache.
@@ -3100,9 +3088,7 @@
IRGenModule::getAddrOfTypeMetadataInstantiationCache(NominalTypeDecl *D,
ForDefinition_t forDefinition) {
auto entity = LinkEntity::forTypeMetadataInstantiationCache(D);
- auto ty = llvm::ArrayType::get(Int8PtrTy, NumGenericMetadataPrivateDataWords);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(),
- forDefinition, ty, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}
llvm::Function *
@@ -3186,9 +3172,8 @@
IRGen.noteUseOfTypeContextDescriptor(D, requireMetadata);
auto entity = LinkEntity::forNominalTypeDescriptor(D);
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- TypeContextDescriptorTy,
DebugTypeInfo());
}
@@ -3196,9 +3181,8 @@
getAddrOfReflectionBuiltinDescriptor(CanType type,
ConstantInit definition) {
auto entity = LinkEntity::forReflectionBuiltinDescriptor(type);
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- FieldDescriptorTy,
DebugTypeInfo());
}
@@ -3206,9 +3190,8 @@
getAddrOfReflectionFieldDescriptor(CanType type,
ConstantInit definition) {
auto entity = LinkEntity::forReflectionFieldDescriptor(type);
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- FieldDescriptorTy,
DebugTypeInfo());
}
@@ -3216,9 +3199,8 @@
getAddrOfReflectionAssociatedTypeDescriptor(const ProtocolConformance *c,
ConstantInit definition) {
auto entity = LinkEntity::forReflectionAssociatedTypeDescriptor(c);
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- FieldDescriptorTy,
DebugTypeInfo());
}
@@ -3226,9 +3208,8 @@
llvm::Constant *IRGenModule::getAddrOfPropertyDescriptor(AbstractStorageDecl *D,
ConstantInit definition) {
auto entity = LinkEntity::forPropertyDescriptor(D);
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- TypeContextDescriptorTy,
DebugTypeInfo());
}
@@ -3241,15 +3222,14 @@
}
auto entity = LinkEntity::forProtocolDescriptor(D);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
- ProtocolDescriptorStructTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, definition,
+ DebugTypeInfo());
}
llvm::Constant *IRGenModule::getAddrOfProtocolRequirementsBaseDescriptor(
ProtocolDecl *proto) {
auto entity = LinkEntity::forProtocolRequirementsBaseDescriptor(proto);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(),
- ProtocolRequirementStructTy,
+ return getAddrOfLLVMVariable(entity, ConstantInit(),
DebugTypeInfo());
}
@@ -3263,8 +3243,7 @@
llvm::Constant *IRGenModule::getAddrOfAssociatedTypeDescriptor(
AssociatedTypeDecl *assocType) {
auto entity = LinkEntity::forAssociatedTypeDescriptor(assocType);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(),
- ProtocolRequirementStructTy,
+ return getAddrOfLLVMVariable(entity, ConstantInit(),
DebugTypeInfo());
}
@@ -3278,8 +3257,7 @@
llvm::Constant *IRGenModule::getAddrOfAssociatedConformanceDescriptor(
AssociatedConformance conformance) {
auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), ConstantInit(),
- ProtocolRequirementStructTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}
llvm::GlobalValue *IRGenModule::defineAssociatedConformanceDescriptor(
@@ -3293,8 +3271,7 @@
const NormalProtocolConformance *conformance,
ConstantInit definition) {
auto entity = LinkEntity::forProtocolConformanceDescriptor(conformance);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
- ProtocolConformanceDescriptorTy,
+ return getAddrOfLLVMVariable(entity, definition,
DebugTypeInfo());
}
@@ -3348,16 +3325,16 @@
IRGenModule::getAddrOfValueWitnessTable(CanType concreteType,
ConstantInit definition) {
LinkEntity entity = LinkEntity::forValueWitnessTable(concreteType);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
- WitnessTableTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}
static Address getAddrOfSimpleVariable(IRGenModule &IGM,
- llvm::DenseMap<LinkEntity, llvm::Constant*> &cache,
- LinkEntity entity,
- llvm::Type *type,
- Alignment alignment,
- ForDefinition_t forDefinition) {
+ llvm::DenseMap<LinkEntity, llvm::Constant*> &cache,
+ LinkEntity entity,
+ ForDefinition_t forDefinition) {
+ auto alignment = entity.getAlignment(IGM);
+ auto type = entity.getDefaultDeclarationType(IGM);
+
// Check whether it's already cached.
llvm::Constant *&entry = cache[entity];
if (entry) {
@@ -3385,15 +3362,13 @@
ForDefinition_t forDefinition) {
LinkEntity entity = LinkEntity::forFieldOffset(var);
return getAddrOfSimpleVariable(*this, GlobalVars, entity,
- SizeTy, getPointerAlignment(),
forDefinition);
}
Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,
ForDefinition_t forDefinition) {
LinkEntity entity = LinkEntity::forEnumCase(Case);
- auto addr = getAddrOfSimpleVariable(*this, GlobalVars, entity, Int32Ty,
- getPointerAlignment(), forDefinition);
+ auto addr = getAddrOfSimpleVariable(*this, GlobalVars, entity, forDefinition);
auto *global = cast<llvm::GlobalVariable>(addr.getAddress());
global->setConstant(true);
@@ -3729,8 +3704,8 @@
assert(!conformingType->hasArchetype());
LinkEntity entity =
LinkEntity::forProtocolWitnessTableLazyCacheVariable(conf, conformingType);
- auto variable = getAddrOfLLVMVariable(entity, getPointerAlignment(),
- forDefinition, WitnessTablePtrTy,
+ auto variable = getAddrOfLLVMVariable(entity,
+ forDefinition,
DebugTypeInfo());
// Zero-initialize if we're asking for a definition.
@@ -3751,8 +3726,7 @@
IRGen.addLazyWitnessTable(conf);
auto entity = LinkEntity::forDirectProtocolWitnessTable(conf);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
- WitnessTableTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}
/// Look up the address of a witness table pattern.
@@ -3765,8 +3739,7 @@
IRGen.addLazyWitnessTable(conf);
auto entity = LinkEntity::forProtocolWitnessTablePattern(conf);
- return getAddrOfLLVMVariable(entity, getPointerAlignment(), definition,
- WitnessTableTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}
llvm::Function *
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 028c140..de875cd 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1552,19 +1552,16 @@
// The class containing the base method.
auto *baseClass = cast<ClassDecl>(baseRef.getDecl()->getDeclContext());
+ IGM.IRGen.noteUseOfTypeContextDescriptor(baseClass, DontRequireMetadata);
auto baseClassEntity = LinkEntity::forNominalTypeDescriptor(baseClass);
auto baseClassDescriptor =
- IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- baseClassEntity, IGM.getPointerAlignment(),
- IGM.Int8Ty);
+ IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseClassEntity);
descriptor.addRelativeAddress(baseClassDescriptor);
// The base method.
auto baseMethodEntity = LinkEntity::forMethodDescriptor(baseRef);
auto baseMethodDescriptor =
- IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- baseMethodEntity, Alignment(4),
- IGM.MethodDescriptorStructTy);
+ IGM.getAddrOfLLVMVariableOrGOTEquivalent(baseMethodEntity);
descriptor.addRelativeAddress(baseMethodDescriptor);
// The implementation of the override.
@@ -1714,9 +1711,8 @@
}
}
- return getAddrOfLLVMVariable(entity, Alignment(4),
+ return getAddrOfLLVMVariable(entity,
definition,
- TypeContextDescriptorTy,
DebugTypeInfo());
}
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 8d329e7..4719410 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2046,8 +2046,7 @@
// Relative reference to the protocol descriptor.
auto protocol = Conformance->getProtocol();
auto descriptorRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forProtocolDescriptor(protocol),
- IGM.getPointerAlignment(), IGM.ProtocolDescriptorStructTy);
+ LinkEntity::forProtocolDescriptor(protocol));
B.addRelativeAddress(descriptorRef);
}
@@ -2143,8 +2142,7 @@
auto assocType = entry.getAssociatedTypeWitness().Requirement;
auto assocTypeDescriptor =
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forAssociatedTypeDescriptor(assocType),
- Alignment(4), IGM.ProtocolRequirementStructTy);
+ LinkEntity::forAssociatedTypeDescriptor(assocType));
B.addRelativeAddress(assocTypeDescriptor);
} else if (entry.getKind() == SILWitnessTable::AssociatedTypeProtocol) {
// Associated conformance descriptor.
@@ -2156,16 +2154,14 @@
witness.Protocol);
auto assocConformanceDescriptor =
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forAssociatedConformanceDescriptor(requirement),
- Alignment(4), IGM.ProtocolRequirementStructTy);
+ LinkEntity::forAssociatedConformanceDescriptor(requirement));
B.addRelativeAddress(assocConformanceDescriptor);
} else if (entry.getKind() == SILWitnessTable::Method) {
// Method descriptor.
auto declRef = entry.getMethodWitness().Requirement;
auto requirement =
IGM.getAddrOfLLVMVariableOrGOTEquivalent(
- LinkEntity::forMethodDescriptor(declRef),
- Alignment(4), IGM.ProtocolRequirementStructTy);
+ LinkEntity::forMethodDescriptor(declRef));
B.addRelativeAddress(requirement);
} else {
// Not part of the resilient witness table.
diff --git a/lib/IRGen/GenThunk.cpp b/lib/IRGen/GenThunk.cpp
index 9a8e547..e9f0872 100644
--- a/lib/IRGen/GenThunk.cpp
+++ b/lib/IRGen/GenThunk.cpp
@@ -129,8 +129,7 @@
assert(declRef.getOverriddenWitnessTableEntry() == declRef &&
"Overriding protocol requirements do not have method descriptors");
LinkEntity entity = LinkEntity::forMethodDescriptor(declRef);
- return getAddrOfLLVMVariable(entity, Alignment(4), forDefinition,
- MethodDescriptorStructTy, DebugTypeInfo());
+ return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}
/// Fetch the method lookup function for a resilient class.
diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp
index 7ece4ac..107498b 100644
--- a/lib/IRGen/IRGenMangler.cpp
+++ b/lib/IRGen/IRGenMangler.cpp
@@ -79,37 +79,70 @@
}
SymbolicMangling
-IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
- Type Ty) {
+IRGenMangler::withSymbolicReferences(IRGenModule &IGM,
+ llvm::function_ref<void ()> body) {
Mod = IGM.getSwiftModule();
OptimizeProtocolNames = false;
- llvm::SaveAndRestore<std::function<bool (const DeclContext *)>>
- SymbolicReferencesForLocalTypes(CanSymbolicReference);
-
- if (IGM.CurSourceFile
- && !isa<ClangModuleUnit>(IGM.CurSourceFile)
- && !IGM.getOptions().IntegratedREPL) {
- CanSymbolicReference = [&](const DeclContext *dc) -> bool {
- // Symbolically reference types that are defined in the same file unit
- // as we're referencing from.
- //
- // We could eventually improve this to reference any type that ends
- // up with its nominal type descriptor in the same linked binary as us,
- // but IRGen doesn't know that with much certainty currently.
- return dc->getModuleScopeContext() == IGM.CurSourceFile
- && isa<NominalTypeDecl>(dc)
- && !isa<ProtocolDecl>(dc);
- };
- }
-
+ llvm::SaveAndRestore<bool>
+ AllowSymbolicReferencesLocally(AllowSymbolicReferences);
+ llvm::SaveAndRestore<std::function<bool (SymbolicReferent)>>
+ CanSymbolicReferenceLocally(CanSymbolicReference);
+
+ AllowSymbolicReferences = true;
+ CanSymbolicReference = [&IGM](SymbolicReferent s) -> bool {
+ if (auto type = s.dyn_cast<const NominalTypeDecl *>()) {
+ // FIXME: Sometimes we fail to emit metadata for Clang imported types
+ // even after noting use of their type descriptor or metadata. Work
+ // around by not symbolic-referencing imported types for now.
+ if (type->hasClangNode())
+ return false;
+
+ // TODO: We ought to be able to use indirect symbolic references even
+ // when the referent may be in another file, once the on-disk
+ // ObjectMemoryReader can handle them.
+ if (!IGM.CurSourceFile || IGM.CurSourceFile != type->getParentSourceFile())
+ return false;
+
+ // @objc protocols don't have descriptors.
+ if (auto proto = dyn_cast<ProtocolDecl>(type))
+ if (proto->isObjC())
+ return false;
+
+ return true;
+ } else {
+ llvm_unreachable("symbolic referent not handled");
+ }
+ };
SymbolicReferences.clear();
- appendType(Ty);
+ body();
return {finalize(), std::move(SymbolicReferences)};
}
+SymbolicMangling
+IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
+ Type Ty) {
+ return withSymbolicReferences(IGM, [&]{
+ appendType(Ty);
+ });
+}
+
+SymbolicMangling
+IRGenMangler::mangleProtocolConformanceForReflection(IRGenModule &IGM,
+ Type ty, ProtocolConformanceRef conformance) {
+ return withSymbolicReferences(IGM, [&]{
+ if (conformance.isConcrete()) {
+ appendProtocolConformance(conformance.getConcrete());
+ } else {
+ // Use a special mangling for abstract conformances.
+ appendType(ty);
+ appendProtocolName(conformance.getAbstract());
+ }
+ });
+}
+
std::string IRGenMangler::mangleTypeForLLVMTypeName(CanType Ty) {
// To make LLVM IR more readable we always add a 'T' prefix so that type names
// don't start with a digit and don't need to be quoted.
@@ -183,12 +216,19 @@
for (auto &symbol : mangling.SymbolicReferences) {
// Fill in the placeholder space with something printable.
- auto dc = symbol.first;
+ auto referent = symbol.first;
auto offset = symbol.second;
- Storage[prefixLen + offset] = Storage[prefixLen + offset+1] =
- Storage[prefixLen + offset+2] = Storage[prefixLen + offset+3] = '_';
+ Storage[prefixLen + offset]
+ = Storage[prefixLen + offset+1]
+ = Storage[prefixLen + offset+2]
+ = Storage[prefixLen + offset+3]
+ = Storage[prefixLen + offset+4]
+ = '_';
Buffer << ' ';
- appendContext(dc);
+ if (auto ty = referent.dyn_cast<const NominalTypeDecl*>())
+ appendContext(ty);
+ else
+ llvm_unreachable("unhandled referent");
}
return finalize();
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index 3c1eb22..11551a9 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -30,7 +30,8 @@
/// A mangling string that includes embedded symbolic references.
struct SymbolicMangling {
std::string String;
- std::vector<std::pair<const DeclContext *, unsigned>> SymbolicReferences;
+ std::vector<std::pair<Mangle::ASTMangler::SymbolicReferent, unsigned>>
+ SymbolicReferences;
};
/// The mangler for all kind of symbols produced in IRGen.
@@ -412,6 +413,10 @@
SymbolicMangling mangleTypeForReflection(IRGenModule &IGM,
Type Ty);
+
+ SymbolicMangling mangleProtocolConformanceForReflection(IRGenModule &IGM,
+ Type Ty,
+ ProtocolConformanceRef conformance);
std::string mangleTypeForLLVMTypeName(CanType Ty);
@@ -421,6 +426,9 @@
const SymbolicMangling &mangling,
MangledTypeRefRole role);
protected:
+ SymbolicMangling
+ withSymbolicReferences(IRGenModule &IGM,
+ llvm::function_ref<void ()> body);
std::string mangleTypeSymbol(Type type, const char *Op) {
beginMangling();
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 84db7b8..daba542 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -1321,7 +1321,8 @@
ForDefinition_t forDefinition);
llvm::Constant *getAddrOfWitnessTable(const NormalProtocolConformance *C,
ConstantInit definition = ConstantInit());
- llvm::Constant *getAddrOfWitnessTablePattern(const NormalProtocolConformance *C,
+ llvm::Constant *getAddrOfWitnessTablePattern(
+ const NormalProtocolConformance *C,
ConstantInit definition = ConstantInit());
llvm::Function *
@@ -1341,8 +1342,7 @@
GenericEnvironment *getGenericEnvironment();
ConstantReference
- getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity, Alignment alignment,
- llvm::Type *defaultType,
+ getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
ConstantReference::Directness forceIndirect = ConstantReference::Direct);
llvm::Constant *
@@ -1376,21 +1376,17 @@
llvm::function_ref<void()> emit);
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
- Alignment alignment,
ConstantInit definition,
- llvm::Type *defaultType,
- DebugTypeInfo debugType);
+ DebugTypeInfo debugType,
+ llvm::Type *overrideDeclType = nullptr);
llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity,
- Alignment alignment,
ForDefinition_t forDefinition,
- llvm::Type *defaultType,
DebugTypeInfo debugType);
ConstantReference getAddrOfLLVMVariable(LinkEntity entity,
- Alignment alignment,
ConstantInit definition,
- llvm::Type *defaultType,
DebugTypeInfo debugType,
- SymbolReferenceKind refKind);
+ SymbolReferenceKind refKind,
+ llvm::Type *overrideDeclType = nullptr);
void emitLazyPrivateDefinitions();
void addRuntimeResolvableType(NominalTypeDecl *nominal);
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index f8f1a21..70dd96e 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -639,3 +639,238 @@
}
llvm_unreachable("bad link entity kind");
}
+
+llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const {
+ switch (getKind()) {
+ case Kind::ModuleDescriptor:
+ case Kind::ExtensionDescriptor:
+ case Kind::AnonymousDescriptor:
+ case Kind::NominalTypeDescriptor:
+ case Kind::PropertyDescriptor:
+ return IGM.TypeContextDescriptorTy;
+ case Kind::ProtocolDescriptor:
+ return IGM.ProtocolDescriptorStructTy;
+ case Kind::AssociatedTypeDescriptor:
+ case Kind::AssociatedConformanceDescriptor:
+ case Kind::ProtocolRequirementsBaseDescriptor:
+ return IGM.ProtocolRequirementStructTy;
+ case Kind::ProtocolConformanceDescriptor:
+ return IGM.ProtocolConformanceDescriptorTy;
+ case Kind::ObjCClassRef:
+ return IGM.ObjCClassPtrTy;
+ case Kind::ObjCClass:
+ case Kind::ObjCMetaclass:
+ case Kind::SwiftMetaclassStub:
+ return IGM.ObjCClassStructTy;
+ case Kind::TypeMetadataLazyCacheVariable:
+ return IGM.TypeMetadataPtrTy;
+ case Kind::TypeMetadataSingletonInitializationCache:
+ // TODO: put a cache variable on IGM
+ return llvm::StructType::get(IGM.getLLVMContext(),
+ {IGM.TypeMetadataPtrTy, IGM.Int8PtrTy});
+ case Kind::TypeMetadata:
+ switch (getMetadataAddress()) {
+ case TypeMetadataAddress::FullMetadata:
+ if (getType().getClassOrBoundGenericClass())
+ return IGM.FullHeapMetadataStructTy;
+ else
+ return IGM.FullTypeMetadataStructTy;
+ case TypeMetadataAddress::AddressPoint:
+ return IGM.TypeMetadataStructTy;
+ }
+
+ case Kind::TypeMetadataPattern:
+ // TODO: Use a real type?
+ return IGM.Int8Ty;
+
+ case Kind::ClassMetadataBaseOffset:
+ // TODO: put a cache variable on IGM
+ return llvm::StructType::get(IGM.getLLVMContext(), {
+ IGM.SizeTy, // Immediate members offset
+ IGM.Int32Ty, // Negative size in words
+ IGM.Int32Ty // Positive size in words
+ });
+
+ case Kind::TypeMetadataInstantiationCache:
+ // TODO: put a cache variable on IGM
+ return llvm::ArrayType::get(IGM.Int8PtrTy,
+ NumGenericMetadataPrivateDataWords);
+ case Kind::ReflectionBuiltinDescriptor:
+ case Kind::ReflectionFieldDescriptor:
+ case Kind::ReflectionAssociatedTypeDescriptor:
+ return IGM.FieldDescriptorTy;
+ case Kind::ValueWitnessTable:
+ case Kind::DirectProtocolWitnessTable:
+ case Kind::ProtocolWitnessTablePattern:
+ return IGM.WitnessTableTy;
+ case Kind::FieldOffset:
+ return IGM.SizeTy;
+ case Kind::EnumCase:
+ return IGM.Int32Ty;
+ case Kind::ProtocolWitnessTableLazyCacheVariable:
+ return IGM.WitnessTablePtrTy;
+ case Kind::SILFunction:
+ return IGM.FunctionPtrTy->getPointerTo();
+ case Kind::MethodDescriptor:
+ case Kind::MethodDescriptorInitializer:
+ case Kind::MethodDescriptorAllocator:
+ return IGM.MethodDescriptorStructTy;
+
+ default:
+ llvm_unreachable("declaration LLVM type not specified");
+ }
+}
+
+Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
+ switch (getKind()) {
+ case Kind::ModuleDescriptor:
+ case Kind::ExtensionDescriptor:
+ case Kind::AnonymousDescriptor:
+ case Kind::NominalTypeDescriptor:
+ case Kind::ProtocolDescriptor:
+ case Kind::AssociatedTypeDescriptor:
+ case Kind::AssociatedConformanceDescriptor:
+ case Kind::ProtocolConformanceDescriptor:
+ case Kind::ProtocolRequirementsBaseDescriptor:
+ case Kind::ReflectionBuiltinDescriptor:
+ case Kind::ReflectionFieldDescriptor:
+ case Kind::ReflectionAssociatedTypeDescriptor:
+ case Kind::PropertyDescriptor:
+ case Kind::EnumCase:
+ case Kind::MethodDescriptor:
+ case Kind::MethodDescriptorInitializer:
+ case Kind::MethodDescriptorAllocator:
+ return Alignment(4);
+ case Kind::ObjCClassRef:
+ case Kind::ObjCClass:
+ case Kind::TypeMetadataLazyCacheVariable:
+ case Kind::TypeMetadataSingletonInitializationCache:
+ case Kind::TypeMetadata:
+ case Kind::TypeMetadataPattern:
+ case Kind::ClassMetadataBaseOffset:
+ case Kind::TypeMetadataInstantiationCache:
+ case Kind::ValueWitnessTable:
+ case Kind::FieldOffset:
+ case Kind::ProtocolWitnessTableLazyCacheVariable:
+ case Kind::DirectProtocolWitnessTable:
+ case Kind::ProtocolWitnessTablePattern:
+ case Kind::ObjCMetaclass:
+ case Kind::SwiftMetaclassStub:
+ return IGM.getPointerAlignment();
+ case Kind::SILFunction:
+ return Alignment(1);
+ default:
+ llvm_unreachable("alignment not specified");
+ }
+}
+
+const SourceFile *LinkEntity::getSourceFileForEmission() const {
+ const SourceFile *sf;
+
+ // Shared-linkage entities don't get emitted with any particular file.
+ if (hasSharedVisibility(getLinkage(NotForDefinition)))
+ return nullptr;
+
+ auto getSourceFileForDeclContext =
+ [](const DeclContext *dc) -> const SourceFile * {
+ if (!dc)
+ return nullptr;
+ return dc->getParentSourceFile();
+ };
+
+ switch (getKind()) {
+ case Kind::DispatchThunk:
+ case Kind::DispatchThunkInitializer:
+ case Kind::DispatchThunkAllocator:
+ case Kind::MethodDescriptor:
+ case Kind::MethodDescriptorInitializer:
+ case Kind::MethodDescriptorAllocator:
+ case Kind::MethodLookupFunction:
+ case Kind::EnumCase:
+ case Kind::FieldOffset:
+ case Kind::ObjCClass:
+ case Kind::ObjCMetaclass:
+ case Kind::SwiftMetaclassStub:
+ case Kind::ClassMetadataBaseOffset:
+ case Kind::PropertyDescriptor:
+ case Kind::NominalTypeDescriptor:
+ case Kind::TypeMetadataPattern:
+ case Kind::TypeMetadataInstantiationCache:
+ case Kind::TypeMetadataInstantiationFunction:
+ case Kind::TypeMetadataSingletonInitializationCache:
+ case Kind::TypeMetadataCompletionFunction:
+ case Kind::ProtocolDescriptor:
+ case Kind::ProtocolRequirementsBaseDescriptor:
+ case Kind::AssociatedTypeDescriptor:
+ case Kind::AssociatedConformanceDescriptor:
+ case Kind::DefaultAssociatedConformanceAccessor:
+ sf = getSourceFileForDeclContext(getDecl()->getDeclContext());
+ if (!sf)
+ return nullptr;
+ break;
+
+ case Kind::SILFunction:
+ sf = getSourceFileForDeclContext(getSILFunction()->getDeclContext());
+ if (!sf)
+ return nullptr;
+ break;
+
+ case Kind::SILGlobalVariable:
+ if (auto decl = getSILGlobalVariable()->getDecl()) {
+ sf = getSourceFileForDeclContext(decl->getDeclContext());
+ if (!sf)
+ return nullptr;
+ } else {
+ return nullptr;
+ }
+ break;
+
+ case Kind::DirectProtocolWitnessTable:
+ case Kind::ProtocolWitnessTablePattern:
+ case Kind::ProtocolWitnessTableAccessFunction:
+ case Kind::GenericProtocolWitnessTableInstantiationFunction:
+ case Kind::AssociatedTypeWitnessTableAccessFunction:
+ case Kind::ReflectionAssociatedTypeDescriptor:
+ case Kind::ProtocolConformanceDescriptor:
+ case Kind::ProtocolWitnessTableLazyCacheVariable:
+ case Kind::ProtocolWitnessTableLazyAccessFunction:
+ sf = getSourceFileForDeclContext(
+ getProtocolConformance()->getRootNormalConformance()->getDeclContext());
+ if (!sf)
+ return nullptr;
+ break;
+
+ case Kind::TypeMetadata: {
+ auto ty = getType();
+ // Only fully concrete nominal type metadata gets emitted eagerly.
+ auto nom = ty->getAnyNominal();
+ if (!nom || nom->isGenericContext())
+ return nullptr;
+
+ sf = getSourceFileForDeclContext(nom);
+ if (!sf)
+ return nullptr;
+ break;
+ }
+
+ // Always shared linkage
+ case Kind::ModuleDescriptor:
+ case Kind::ExtensionDescriptor:
+ case Kind::AnonymousDescriptor:
+ case Kind::ObjCClassRef:
+ case Kind::TypeMetadataAccessFunction:
+ case Kind::TypeMetadataLazyCacheVariable:
+ case Kind::ForeignTypeMetadataCandidate:
+ return nullptr;
+
+ // TODO
+ case Kind::CoroutineContinuationPrototype:
+ case Kind::ReflectionFieldDescriptor:
+ case Kind::ReflectionBuiltinDescriptor:
+ case Kind::ValueWitness:
+ case Kind::ValueWitnessTable:
+ return nullptr;
+ }
+
+ return sf;
+}
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index da05192..61d8397 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -34,6 +34,7 @@
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/ClangImporter/ClangModule.h"
+#include "swift/IRGen/Linking.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/TypeLowering.h"
@@ -261,22 +262,40 @@
// Emit the preceding literal chunk.
auto literalChunk = StringRef(mangling.String.data() + pos,
symbolic.second - pos);
- assert(literalChunk.back() == '\1' && "should be prefixed with \\1");
auto literal = llvm::ConstantDataArray::getString(getLLVMContext(),
literalChunk,
/*null*/ false);
S.add(literal);
}
- // The symbolic reference is to the type context descriptor of the
- // referenced type.
- // We currently only allow symbolic references to nominal type contexts.
- auto nominal = cast<NominalTypeDecl>(symbolic.first);
- S.addRelativeAddress(
- getAddrOfTypeContextDescriptor(const_cast<NominalTypeDecl*>(nominal),
- DontRequireMetadata));
+ ConstantReference ref;
+ unsigned char baseKind;
+ if (auto ctype = symbolic.first.dyn_cast<const NominalTypeDecl*>()) {
+ auto type = const_cast<NominalTypeDecl*>(ctype);
+ if (auto proto = dyn_cast<ProtocolDecl>(type)) {
+ // The symbolic reference is to the protocol descriptor of the
+ // referenced protocol.
+ ref = getAddrOfLLVMVariableOrGOTEquivalent(
+ LinkEntity::forProtocolDescriptor(proto));
+ } else {
+ // The symbolic reference is to the type context descriptor of the
+ // referenced type.
+ IRGen.noteUseOfTypeContextDescriptor(type, DontRequireMetadata);
+ ref = getAddrOfLLVMVariableOrGOTEquivalent(
+ LinkEntity::forNominalTypeDescriptor(type));
+ }
+ // \1 - direct reference, \2 - indirect reference
+ baseKind = 1;
+ } else {
+ llvm_unreachable("unhandled symbolic referent");
+ }
- pos = symbolic.second + 4;
+ // add kind byte. indirect kinds are the direct kind + 1
+ unsigned char kind = ref.isIndirect() ? baseKind + 1 : baseKind;
+ S.add(llvm::ConstantInt::get(Int8Ty, kind));
+ // add relative reference
+ S.addRelativeAddress(ref.getValue());
+ pos = symbolic.second + 5;
}
// Add the last literal bit, if any.
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index adc35fe..cdb6641 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -54,17 +54,88 @@
// Resolve symbolic references to type contexts into the absolute address of
// the type context descriptor, so that if we see a symbolic reference in the
// mangled name we can immediately find the associated metadata.
- dem.setSymbolicReferenceResolver([&](int32_t offset,
- const void *base) -> NodePointer {
- auto absolute_addr = (uintptr_t)detail::applyRelativeOffset(base, offset);
- auto reference = dem.createNode(Node::Kind::SymbolicReference, absolute_addr);
- auto type = dem.createNode(Node::Kind::Type);
- type->addChild(reference, dem);
- return type;
- });
+ dem.setSymbolicReferenceResolver(ResolveAsSymbolicReference(dem));
return dem;
}
+NodePointer
+ResolveAsSymbolicReference::operator()(SymbolicReferenceKind kind,
+ Directness isIndirect,
+ int32_t offset,
+ const void *base) {
+ // Resolve the absolute pointer to the entity being referenced.
+ auto ptr = detail::applyRelativeOffset(base, offset);
+ if (isIndirect == Directness::Indirect) {
+ ptr = *(const uintptr_t *)ptr;
+ }
+
+ // Figure out this symbolic reference's grammatical role.
+ Node::Kind nodeKind;
+ bool isType;
+ switch (kind) {
+ case Demangle::SymbolicReferenceKind::Context: {
+ auto descriptor = (const ContextDescriptor *)ptr;
+ switch (descriptor->getKind()) {
+ case ContextDescriptorKind::Protocol:
+ nodeKind = Node::Kind::ProtocolSymbolicReference;
+ isType = false;
+ break;
+
+ default:
+ if (auto typeContext = dyn_cast<TypeContextDescriptor>(descriptor)) {
+ nodeKind = Node::Kind::TypeSymbolicReference;
+ isType = true;
+ break;
+ }
+
+ // References to other kinds of context aren't yet implemented.
+ return nullptr;
+ }
+ break;
+ }
+ }
+
+ auto node = Dem.createNode(nodeKind, ptr);
+ if (isType) {
+ auto typeNode = Dem.createNode(Node::Kind::Type);
+ typeNode->addChild(node, Dem);
+ node = typeNode;
+ }
+ return node;
+}
+
+static NodePointer
+_buildDemanglingForSymbolicReference(SymbolicReferenceKind kind,
+ const void *resolvedReference,
+ Demangler &Dem) {
+ switch (kind) {
+ case SymbolicReferenceKind::Context:
+ return _buildDemanglingForContext(
+ (const ContextDescriptor *)resolvedReference, {}, Dem);
+ }
+
+ swift_runtime_unreachable("invalid symbolic reference kind");
+}
+
+NodePointer
+ResolveToDemanglingForContext::operator()(SymbolicReferenceKind kind,
+ Directness isIndirect,
+ int32_t offset,
+ const void *base) {
+ auto ptr = detail::applyRelativeOffset(base, offset);
+ if (isIndirect == Directness::Indirect) {
+ ptr = *(const uintptr_t *)ptr;
+ }
+
+ return _buildDemanglingForSymbolicReference(kind, (const void *)ptr, Dem);
+}
+
+NodePointer
+ExpandResolvedSymbolicReferences::operator()(SymbolicReferenceKind kind,
+ const void *ptr) {
+ return _buildDemanglingForSymbolicReference(kind, (const void *)ptr, Dem);
+}
+
#pragma mark Nominal type descriptor cache
// Type Metadata Cache.
@@ -310,10 +381,13 @@
node = node->getChild(0);
// We can directly match symbolic references to the current context.
- if (node && node->getKind() == Demangle::Node::Kind::SymbolicReference) {
- if (equalContexts(context, reinterpret_cast<const ContextDescriptor *>(
- node->getIndex()))) {
- return true;
+ if (node) {
+ if (node->getKind() == Demangle::Node::Kind::TypeSymbolicReference
+ || node->getKind() == Demangle::Node::Kind::ProtocolSymbolicReference){
+ if (equalContexts(context,
+ reinterpret_cast<const ContextDescriptor *>(node->getIndex()))) {
+ return true;
+ }
}
}
@@ -518,17 +592,12 @@
NodePointer symbolicNode = node;
if (symbolicNode->getKind() == Node::Kind::Type)
symbolicNode = symbolicNode->getChild(0);
- if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
+ if (symbolicNode->getKind() == Node::Kind::TypeSymbolicReference)
return cast<TypeContextDescriptor>(
(const ContextDescriptor *)symbolicNode->getIndex());
auto mangledName =
- Demangle::mangleNode(node,
- [&](const void *context) -> NodePointer {
- return _buildDemanglingForContext(
- (const ContextDescriptor *) context,
- {}, Dem);
- });
+ Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem));
// Look for an existing entry.
// Find the bucket for the metadata entry.
@@ -653,17 +722,12 @@
NodePointer symbolicNode = node;
if (symbolicNode->getKind() == Node::Kind::Type)
symbolicNode = symbolicNode->getChild(0);
- if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
+ if (symbolicNode->getKind() == Node::Kind::ProtocolSymbolicReference)
return cast<ProtocolDescriptor>(
(const ContextDescriptor *)symbolicNode->getIndex());
mangledName =
- Demangle::mangleNode(node,
- [&](const void *context) -> NodePointer {
- return _buildDemanglingForContext(
- (const ContextDescriptor *) context,
- {}, Dem);
- });
+ Demangle::mangleNode(node, ExpandResolvedSymbolicReferences(Dem));
// Look for an existing entry.
// Find the bucket for the metadata entry.
@@ -1155,13 +1219,23 @@
// Check whether this is the convenience syntax "ModuleName.ClassName".
auto getDotPosForConvenienceSyntax = [&]() -> size_t {
- size_t dotPos = typeName.find('.');
- if (dotPos == llvm::StringRef::npos)
- return llvm::StringRef::npos;
- if (typeName.find('.', dotPos + 1) != llvm::StringRef::npos)
- return llvm::StringRef::npos;
- if (typeName.find('\1') != llvm::StringRef::npos)
- return llvm::StringRef::npos;
+ size_t dotPos = llvm::StringRef::npos;
+ for (unsigned i = 0; i < typeName.size(); ++i) {
+ // Should only contain one dot.
+ if (typeName[i] == '.') {
+ if (dotPos == llvm::StringRef::npos) {
+ dotPos = i;
+ continue;
+ } else {
+ return llvm::StringRef::npos;
+ }
+ }
+
+ // Should not contain symbolic references.
+ if ((unsigned char)typeName[i] <= '\x1F') {
+ return llvm::StringRef::npos;
+ }
+ }
return dotPos;
};
diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h
index d04866f..f1b6961 100644
--- a/stdlib/public/runtime/Private.h
+++ b/stdlib/public/runtime/Private.h
@@ -404,12 +404,36 @@
explicit ResolveToDemanglingForContext(Demangle::Demangler &Dem)
: Dem(Dem) {}
- Demangle::NodePointer operator()(int32_t offset, const void *base) {
- auto descriptor =
- (const ContextDescriptor *)detail::applyRelativeOffset(base, offset);
-
- return _buildDemanglingForContext(descriptor, {}, Dem);
- }
+ Demangle::NodePointer operator()(Demangle::SymbolicReferenceKind kind,
+ Demangle::Directness isIndirect,
+ int32_t offset,
+ const void *base);
+ };
+
+ /// Symbolic reference resolver that resolves the absolute addresses of
+ /// symbolic references but leaves them as references.
+ class ResolveAsSymbolicReference {
+ Demangle::Demangler &Dem;
+ public:
+ explicit ResolveAsSymbolicReference(Demangle::Demangler &Dem)
+ : Dem(Dem) {}
+
+ Demangle::NodePointer operator()(Demangle::SymbolicReferenceKind kind,
+ Demangle::Directness isIndirect,
+ int32_t offset,
+ const void *base);
+ };
+
+ /// Demangler resolver that turns resolved symbolic references into their
+ /// demangling trees.
+ class ExpandResolvedSymbolicReferences {
+ Demangle::Demangler &Dem;
+ public:
+ explicit ExpandResolvedSymbolicReferences(Demangle::Demangler &Dem)
+ : Dem(Dem) {}
+
+ Demangle::NodePointer operator()(Demangle::SymbolicReferenceKind kind,
+ const void *resolvedReference);
};
/// Is the given type imported from a C tag type?
diff --git a/test/IRGen/class_metadata.swift b/test/IRGen/class_metadata.swift
index abcc61d..d79b78e 100644
--- a/test/IRGen/class_metadata.swift
+++ b/test/IRGen/class_metadata.swift
@@ -51,7 +51,7 @@
// Metadata access function.
// CHECK-SAME: i32 {{.*}} @"$s14class_metadata1BCMa"
// Superclass type.
-// CHECK-SAME: @"symbolic \01____ 14class_metadata1AC"
+// CHECK-SAME: @"symbolic _____ 14class_metadata1AC"
// Negative size in words.
// CHECK-SAME: i32 2,
// Positive size in words.
@@ -89,7 +89,7 @@
// Metadata access function.
// CHECK-SAME: i32 {{.*}} @"$s14class_metadata1CCMa"
// Superclass type.
-// CHECK-SAME: @"symbolic \01____ 14class_metadata1BC"
+// CHECK-SAME: @"symbolic _____ 14class_metadata1BC"
// Negative size in words.
// CHECK-SAME: i32 2,
// Positive size in words.
@@ -150,7 +150,7 @@
// Metadata access function.
// CHECK-SAME: i32 {{.*}} @"$s14class_metadata1DCMa"
// Superclass type.
-// CHECK-SAME: @"symbolic \01____ 14class_metadata1EC"
+// CHECK-SAME: @"symbolic _____ 14class_metadata1EC"
// Negative size in words.
// CHECK-SAME: i32 2,
// Positive size in words.
@@ -167,14 +167,14 @@
// CHECK-SAME: i32 1,
// CHECK-SAME: %swift.method_override_descriptor {
// Override table entry #1: base class.
-// CHECK-SAME: @"got.$s14class_metadata1ECMn.1"
+// CHECK-SAME: @"$s14class_metadata1ECMn"
// Override table entry #1: base method.
-// CHECK-SAME: @"got.$s14class_metadata1ECACycfCTq"
+// CHECK-SAME: @"$s14class_metadata1ECMn"
// Override table entry #1: invocation function.
// CHECK-SAME: @"$s14class_metadata1DCACycfC"
// CHECK-SAME: }>, section
class E {}
// CHECK-LABEL: @"$s14class_metadata1FCMn" =
-// CHECK-SAME: @"symbolic \01____yq_G 14class_metadata1CC"
+// CHECK-SAME: @"symbolic _____yq_G 14class_metadata1CC"
class F<T, U> : C<U> { }
diff --git a/test/IRGen/protocol_resilience_descriptors.swift b/test/IRGen/protocol_resilience_descriptors.swift
index 9e6d766..2af58e7 100644
--- a/test/IRGen/protocol_resilience_descriptors.swift
+++ b/test/IRGen/protocol_resilience_descriptors.swift
@@ -23,7 +23,7 @@
// Associated type default + flags
// CHECK-DEFINITION-SAME: [[INT]] add
-// CHECK-DEFINITION-SAME: @"default assoc type \01____y2T118resilient_protocol29ProtocolWithAssocTypeDefaultsPQzG 18resilient_protocol7WrapperV"
+// CHECK-DEFINITION-SAME: @"default assoc type _____y2T118resilient_protocol29ProtocolWithAssocTypeDefaultsPQzG 18resilient_protocol7WrapperV"
// CHECK-DEFINITION-SAME: [[INT]] 1
// Protocol requirements base descriptor
diff --git a/test/Reflection/typeref_decoding.swift b/test/Reflection/typeref_decoding.swift
index 6e8c0b8..401504a 100644
--- a/test/Reflection/typeref_decoding.swift
+++ b/test/Reflection/typeref_decoding.swift
@@ -652,14 +652,14 @@
// CHECK: TypesToReflect.ClassBoundP
// CHECK: --------------------------
-// CHECK: TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})
+// CHECK: TypesToReflect.(FileprivateProtocol in _{{[0-9a-fA-F]+}})
// CHECK: -------------------------------------------------------------------------
// CHECK: TypesToReflect.HasFileprivateProtocol
// CHECK: -------------------------------------
-// CHECK: x: TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})
+// CHECK: x: TypesToReflect.(FileprivateProtocol in ${{[0-9a-fA-F]+}})
// CHECK: (protocol_composition
-// CHECK-NEXT: (protocol TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})))
+// CHECK-NEXT: (protocol TypesToReflect.(FileprivateProtocol in ${{[0-9a-fA-F]+}})))
// CHECK: ASSOCIATED TYPES:
// CHECK: =================
diff --git a/test/Reflection/typeref_decoding_asan.swift b/test/Reflection/typeref_decoding_asan.swift
index 9a40e21..573b601 100644
--- a/test/Reflection/typeref_decoding_asan.swift
+++ b/test/Reflection/typeref_decoding_asan.swift
@@ -657,9 +657,9 @@
// CHECK: TypesToReflect.HasFileprivateProtocol
// CHECK: -------------------------------------
-// CHECK: x: TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})
+// CHECK: x: TypesToReflect.(FileprivateProtocol in ${{[0-9a-fA-F]+}})
// CHECK: (protocol_composition
-// CHECK-NEXT: (protocol TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})))
+// CHECK-NEXT: (protocol TypesToReflect.(FileprivateProtocol in ${{[0-9a-fA-F]+}})))
// CHECK: ASSOCIATED TYPES:
// CHECK: =================