Skip to content

[Reflection] Add support for imported structs with recorded fields (attempt #2) #14399

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
merged 2 commits into from
Feb 7, 2018
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
4 changes: 4 additions & 0 deletions include/swift/Reflection/Records.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ class FieldDescriptor {
Kind == FieldDescriptorKind::ObjCProtocol);
}

bool isStruct() const {
return Kind == FieldDescriptorKind::Struct;
}

const_iterator begin() const {
auto Begin = getFieldRecordBuffer();
auto End = Begin + NumFields;
Expand Down
4 changes: 3 additions & 1 deletion lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5618,7 +5618,9 @@ IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
} else if (auto structType = dyn_cast<StructType>(type)) {
auto structDecl = structType->getDecl();
assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext()));


ImportedStructs.insert(structDecl);

ForeignStructMetadataBuilder builder(*this, structDecl, init);
builder.layout();
addressPoint = builder.getOffsetOfAddressPoint();
Expand Down
9 changes: 7 additions & 2 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,13 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
B.addInt16(fieldRecordSize);

// Imported classes don't need field descriptors
if (NTD->hasClangNode()) {
assert(isa<ClassDecl>(NTD));
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 @@ -435,6 +436,7 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
void layout() override {
if (NTD->hasClangNode() &&
!isa<ClassDecl>(NTD) &&
!isa<StructDecl>(NTD) &&
!isa<ProtocolDecl>(NTD))
return;

Expand Down Expand Up @@ -941,6 +943,9 @@ void IRGenModule::emitBuiltinReflectionMetadata() {
for (auto PD : ImportedProtocols)
emitFieldMetadataRecord(PD);

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

for (auto builtinType : BuiltinTypes)
emitBuiltinTypeMetadataRecord(builtinType);

Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,9 @@ class IRGenModule {
/// 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;

llvm::Constant *getAddrOfStringForTypeRef(StringRef Str);
llvm::Constant *getAddrOfFieldName(StringRef Name);
Expand Down
8 changes: 5 additions & 3 deletions stdlib/public/Reflection/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,16 +1057,18 @@ class LowerType

const TypeInfo *visitAnyNominalTypeRef(const TypeRef *TR) {
const auto &FD = TC.getBuilder().getFieldTypeInfo(TR);
if (FD.first == nullptr) {
if (FD.first == nullptr || FD.first->isStruct()) {
// Maybe this type is opaque -- look for a builtin
// descriptor to see if we at least know its size
// and alignment.
if (auto ImportedTypeDescriptor = TC.getBuilder().getBuiltinTypeInfo(TR))
return TC.makeTypeInfo<BuiltinTypeInfo>(ImportedTypeDescriptor);

// Otherwise, we're out of luck.
DEBUG(std::cerr << "No TypeInfo for nominal type: "; TR->dump());
return nullptr;
if (FD.first == nullptr) {
DEBUG(std::cerr << "No TypeInfo for nominal type: "; TR->dump());
return nullptr;
}
}

switch (FD.first->Kind) {
Expand Down
26 changes: 26 additions & 0 deletions test/Reflection/typeref_decoding_imported.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@
// CHECK-32: mce: __C.MyCEnum
// CHECK-32: (struct __C.MyCEnum)

// CHECK-32: __C.MyCStruct
// CHECK-32: -------------
// CHECK-32: i: Swift.Int32
// CHECK-32: (struct Swift.Int32)

// CHECK-32: ip: Swift.Optional<Swift.UnsafeMutablePointer<Swift.Int32>>
// CHECK-32: (bound_generic_enum Swift.Optional
// CHECK-32: (bound_generic_struct Swift.UnsafeMutablePointer
// CHECK-32: (struct Swift.Int32)))

// CHECK-32: c: Swift.Int8
// CHECK-32: (struct Swift.Int8)

// CHECK-32: TypesToReflect.AlsoHasCTypes
// CHECK-32: ----------------------------

Expand Down Expand Up @@ -82,6 +95,19 @@
// CHECK-64: mcu: __C.MyCUnion
// CHECK-64: (struct __C.MyCUnion)

// CHECK-64: __C.MyCStruct
// CHECK-64: -------------
// CHECK-64: i: Swift.Int32
// CHECK-64: (struct Swift.Int32)

// CHECK-64: ip: Swift.Optional<Swift.UnsafeMutablePointer<Swift.Int32>>
// CHECK-64: (bound_generic_enum Swift.Optional
// CHECK-64: (bound_generic_struct Swift.UnsafeMutablePointer
// CHECK-64: (struct Swift.Int32)))

// CHECK-64: c: Swift.Int8
// CHECK-64: (struct Swift.Int8)

// CHECK-64: TypesToReflect.AlsoHasCTypes
// CHECK-64: ----------------------------

Expand Down