Skip to content

Remove imported reflection field descriptors #20235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "swift/Demangling/Demangler.h"
#include "swift/Basic/LLVM.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Strings.h"
#include <vector>

namespace swift {
Expand Down Expand Up @@ -75,6 +76,34 @@ class FunctionParam {
}
};


#if SWIFT_OBJC_INTEROP
/// For a mangled node that refers to an Objective-C class or protocol,
/// return the class or protocol name.
static inline Optional<StringRef> getObjCClassOrProtocolName(
const Demangle::NodePointer &node) {
if (node->getKind() != Demangle::Node::Kind::Class &&
node->getKind() != Demangle::Node::Kind::Protocol)
return None;

if (node->getNumChildren() != 2)
return None;

// Check whether we have the __ObjC module.
auto moduleNode = node->getChild(0);
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
moduleNode->getText() != MANGLING_MODULE_OBJC)
return None;

// Check whether we have an identifier.
auto nameNode = node->getChild(1);
if (nameNode->getKind() != Demangle::Node::Kind::Identifier)
return None;

return nameNode->getText();
}
#endif

/// Decode a mangled type to construct an abstract type, forming such
/// types by invoking a custom builder.
template <typename BuilderType>
Expand Down Expand Up @@ -112,6 +141,13 @@ class TypeDecoder {

return decodeMangledType(Node->getChild(0));
case NodeKind::Class:
{
#if SWIFT_OBJC_INTEROP
if (auto mangledName = getObjCClassOrProtocolName(Node))
return Builder.createObjCClassType(mangledName->str());
#endif
LLVM_FALLTHROUGH;
}
case NodeKind::Enum:
case NodeKind::Structure:
case NodeKind::TypeAlias: // This can show up for imported Clang decls.
Expand All @@ -125,6 +161,14 @@ class TypeDecoder {
return Builder.createNominalType(typeDecl, parent);
}
case NodeKind::BoundGenericClass:
{
#if SWIFT_OBJC_INTEROP
if (Node->getNumChildren() == 2)
if (auto mangledName = getObjCClassOrProtocolName(Node->getChild(0)))
return Builder.createObjCClassType(mangledName->str());
#endif
LLVM_FALLTHROUGH;
}
case NodeKind::BoundGenericEnum:
case NodeKind::BoundGenericStructure:
case NodeKind::BoundGenericOtherNominalType: {
Expand Down Expand Up @@ -528,6 +572,11 @@ class TypeDecoder {
&& node->getKind() != NodeKind::ProtocolSymbolicReference)
return BuiltProtocolDecl();

#if SWIFT_OBJC_INTEROP
if (auto objcProtocolName = getObjCClassOrProtocolName(node))
return Builder.createObjCProtocolDecl(objcProtocolName->str());
#endif

return Builder.createProtocolDecl(node);
}

Expand Down
41 changes: 36 additions & 5 deletions include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,11 @@ class FunctionTypeRef final : public TypeRef {
};

class ProtocolCompositionTypeRef final : public TypeRef {
std::vector<const NominalTypeRef *> Protocols;
std::vector<const TypeRef *> Protocols;
const TypeRef *Superclass;
bool HasExplicitAnyObject;

static TypeRefID Profile(std::vector<const NominalTypeRef *> Protocols,
static TypeRefID Profile(std::vector<const TypeRef *> Protocols,
const TypeRef *Superclass,
bool HasExplicitAnyObject) {
TypeRefID ID;
Expand All @@ -403,7 +403,7 @@ class ProtocolCompositionTypeRef final : public TypeRef {
}

public:
ProtocolCompositionTypeRef(std::vector<const NominalTypeRef *> Protocols,
ProtocolCompositionTypeRef(std::vector<const TypeRef *> Protocols,
const TypeRef *Superclass,
bool HasExplicitAnyObject)
: TypeRef(TypeRefKind::ProtocolComposition),
Expand All @@ -412,13 +412,14 @@ class ProtocolCompositionTypeRef final : public TypeRef {

template <typename Allocator>
static const ProtocolCompositionTypeRef *
create(Allocator &A, std::vector<const NominalTypeRef *> Protocols,
create(Allocator &A, std::vector<const TypeRef *> Protocols,
const TypeRef *Superclass, bool HasExplicitAnyObject) {
FIND_OR_CREATE_TYPEREF(A, ProtocolCompositionTypeRef, Protocols,
Superclass, HasExplicitAnyObject);
}

const std::vector<const NominalTypeRef *> &getProtocols() const {
// These are either NominalTypeRef or ObjCProtocolTypeRef.
const std::vector<const TypeRef *> &getProtocols() const {
return Protocols;
}

Expand Down Expand Up @@ -633,6 +634,36 @@ class ObjCClassTypeRef final : public TypeRef {
}
};

class ObjCProtocolTypeRef final : public TypeRef {
std::string Name;
static const ObjCProtocolTypeRef *UnnamedSingleton;

static TypeRefID Profile(const std::string &Name) {
TypeRefID ID;
ID.addString(Name);
return ID;
}
public:
ObjCProtocolTypeRef(const std::string &Name)
: TypeRef(TypeRefKind::ObjCProtocol), Name(Name) {}

static const ObjCProtocolTypeRef *getUnnamed();

template <typename Allocator>
static const ObjCProtocolTypeRef *create(Allocator &A,
const std::string &Name) {
FIND_OR_CREATE_TYPEREF(A, ObjCProtocolTypeRef, Name);
}

const std::string &getName() const {
return Name;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::ObjCProtocol;
}
};

class OpaqueTypeRef final : public TypeRef {
static const OpaqueTypeRef *Singleton;

Expand Down
42 changes: 31 additions & 11 deletions include/swift/Reflection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class TypeRefBuilder {
public:
using BuiltType = const TypeRef *;
using BuiltNominalTypeDecl = Optional<std::string>;
using BuiltProtocolDecl = Optional<std::string>;
using BuiltProtocolDecl = Optional<std::pair<std::string, bool /*isObjC*/>>;

TypeRefBuilder();

Expand Down Expand Up @@ -214,9 +214,14 @@ class TypeRefBuilder {
return Demangle::mangleNode(node);
}

Optional<std::string>
BuiltProtocolDecl
createProtocolDecl(const Demangle::NodePointer &node) {
return Demangle::mangleNode(node);
return std::make_pair(Demangle::mangleNode(node), false);
}

BuiltProtocolDecl
createObjCProtocolDecl(std::string &&name) {
return std::make_pair(name, true);
}

Optional<std::string> createNominalTypeDecl(std::string &&mangledName) {
Expand Down Expand Up @@ -265,9 +270,15 @@ class TypeRefBuilder {
createProtocolCompositionType(ArrayRef<BuiltProtocolDecl> protocols,
BuiltType superclass,
bool isClassBound) {
std::vector<const NominalTypeRef *> protocolRefs;
std::vector<const TypeRef *> protocolRefs;
for (const auto &protocol : protocols) {
protocolRefs.push_back(createNominalType(protocol));
if (!protocol)
continue;

if (protocol->second)
protocolRefs.push_back(createObjCProtocolType(protocol->first));
else
protocolRefs.push_back(createNominalType(protocol->first));
}

return ProtocolCompositionTypeRef::create(*this, protocolRefs, superclass,
Expand All @@ -292,8 +303,12 @@ class TypeRefBuilder {
const DependentMemberTypeRef *
createDependentMemberType(const std::string &member,
const TypeRef *base,
Optional<std::string> protocol) {
return DependentMemberTypeRef::create(*this, member, base, *protocol);
BuiltProtocolDecl protocol) {
// Objective-C protocols don't have dependent types.
if (protocol->second)
return nullptr;
return DependentMemberTypeRef::create(*this, member, base,
protocol->first);
}

#define REF_STORAGE(Name, ...) \
Expand All @@ -306,13 +321,18 @@ class TypeRefBuilder {
return SILBoxTypeRef::create(*this, base);
}

const ObjCClassTypeRef *getUnnamedObjCClassType() {
return createObjCClassType("");
}

const ObjCClassTypeRef *
createObjCClassType(const std::string &mangledName) {
return ObjCClassTypeRef::create(*this, mangledName);
createObjCClassType(const std::string &name) {
return ObjCClassTypeRef::create(*this, name);
}

const ObjCClassTypeRef *getUnnamedObjCClassType() {
return createObjCClassType("");
const ObjCProtocolTypeRef *
createObjCProtocolType(const std::string &name) {
return ObjCProtocolTypeRef::create(*this, name);
}

const ForeignClassTypeRef *
Expand Down
1 change: 1 addition & 0 deletions include/swift/Reflection/TypeRefs.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ TYPEREF(GenericTypeParameter, TypeRef)
TYPEREF(DependentMember, TypeRef)
TYPEREF(ForeignClass, TypeRef)
TYPEREF(ObjCClass, TypeRef)
TYPEREF(ObjCProtocol, TypeRef)
TYPEREF(Opaque, TypeRef)
#define REF_STORAGE(Name, ...) \
TYPEREF(Name##Storage, TypeRef)
Expand Down
42 changes: 32 additions & 10 deletions include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,18 +498,39 @@ class MetadataReader {
#if SWIFT_OBJC_INTEROP
// Check whether we have an Objective-C protocol.
if (ProtocolAddress.isObjC()) {
auto MangledNameStr =
auto Name =
readObjCProtocolName(ProtocolAddress.getObjCProtocol());
StringRef NameStr(Name);

// If this is a Swift-defined protocol, demangle it.
if (NameStr.startswith("_TtP")) {
Demangle::Context DCtx;
auto Demangled = DCtx.demangleSymbolAsNode(NameStr);
if (!Demangled)
return BuiltType();

// FIXME: This appears in _swift_buildDemanglingForMetadata().
while (Demangled->getKind() == Node::Kind::Global ||
Demangled->getKind() == Node::Kind::TypeMangling ||
Demangled->getKind() == Node::Kind::Type ||
Demangled->getKind() == Node::Kind::ProtocolList ||
Demangled->getKind() == Node::Kind::TypeList ||
Demangled->getKind() == Node::Kind::Type) {
if (Demangled->getNumChildren() != 1)
return BuiltType();
Demangled = Demangled->getFirstChild();
}

auto Protocol = Builder.createProtocolDecl(Demangled);
if (!Protocol)
return BuiltType();

Protocols.push_back(Protocol);
continue;
}

StringRef MangledName =
Demangle::dropSwiftManglingPrefix(MangledNameStr);

Demangle::Context DCtx;
auto Demangled = DCtx.demangleTypeAsNode(MangledName);
if (!Demangled)
return BuiltType();

auto Protocol = Builder.createProtocolDecl(Demangled);
// Otherwise, this is an imported protocol.
auto Protocol = Builder.createObjCProtocolDecl(NameStr);
if (!Protocol)
return BuiltType();

Expand All @@ -518,6 +539,7 @@ class MetadataReader {
}
#endif

// Swift-native protocol.
Demangle::Demangler Dem;
auto Demangled = readDemanglingForContextDescriptor(
ProtocolAddress.getSwiftProtocol(), Dem);
Expand Down
3 changes: 3 additions & 0 deletions include/swift/RemoteAST/RemoteAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ class RemoteASTContext {
Type staticType);
};

Type getTypeForMangling(ASTContext &ctx,
StringRef mangling);

} // end namespace remoteAST
} // end namespace swift

Expand Down
33 changes: 5 additions & 28 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,16 @@ class ReflectionMetadataBuilder {
if (IGM.getSwiftModule()->isStdlibModule() && isa<BuiltinType>(t))
IGM.BuiltinTypes.insert(t);

// We need size/alignment information for imported value types,
// so emit builtin descriptors for them.
// We need size/alignment information for imported structs and
// enums, so emit builtin descriptors for them.
//
// In effect they're treated like an opaque blob, which is OK
// for now, at least until we want to import C++ types or
// something like that.
//
// Classes and protocols go down a different path.
if (auto Nominal = t->getAnyNominal())
if (Nominal->hasClangNode()) {
if (auto CD = dyn_cast<ClassDecl>(Nominal))
IGM.ImportedClasses.insert(CD);
else if (auto PD = dyn_cast<ProtocolDecl>(Nominal))
IGM.ImportedProtocols.insert(PD);
else
if (isa<StructDecl>(Nominal) ||
isa<EnumDecl>(Nominal))
IGM.OpaqueTypes.insert(Nominal);
}
});
Expand Down Expand Up @@ -386,14 +381,6 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
B.addInt16(uint16_t(kind));
B.addInt16(fieldRecordSize);

// Imported classes don't need field descriptors
if (NTD->hasClangNode() && isa<ClassDecl>(NTD)) {
B.addInt32(0);
return;
}

assert(!NTD->hasClangNode() || isa<StructDecl>(NTD));

auto properties = NTD->getStoredProperties();
B.addInt32(std::distance(properties.begin(), properties.end()));
for (auto property : properties)
Expand Down Expand Up @@ -453,11 +440,7 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
}

void layout() override {
if (NTD->hasClangNode() &&
!isa<ClassDecl>(NTD) &&
!isa<StructDecl>(NTD) &&
!isa<ProtocolDecl>(NTD))
return;
assert(!NTD->hasClangNode() || isa<StructDecl>(NTD));

PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
addNominalRef(NTD);
Expand Down Expand Up @@ -949,12 +932,6 @@ void IRGenModule::emitBuiltinReflectionMetadata() {
BuiltinTypes.insert(anyMetatype);
}

for (auto CD : ImportedClasses)
emitFieldMetadataRecord(CD);

for (auto PD : ImportedProtocols)
emitFieldMetadataRecord(PD);

for (auto SD : ImportedStructs)
emitFieldMetadataRecord(SD);

Expand Down
6 changes: 0 additions & 6 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,12 +1045,6 @@ class IRGenModule {
/// without knowledge of their contents. This includes imported structs
/// and fixed-size multi-payload enums.
llvm::SetVector<const NominalTypeDecl *> OpaqueTypes;
/// Imported classes referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<const ClassDecl *> ImportedClasses;
/// Imported protocols referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<const ProtocolDecl *> ImportedProtocols;
/// Imported structs referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<const StructDecl *> ImportedStructs;
Expand Down
Loading