Skip to content

Add a callback to swift::reflection::MemoryReader that allows LLDB to… #33417

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 5 commits into from
Sep 8, 2020

Conversation

adrian-prantl
Copy link
Contributor

Add a callback to swift::reflection::MemoryReader that allows LLDB to provide

swift::reflection::TypeInfo for (Clang-)imported non-Objective-C types. This is
needed to reflect on the size mixed Swift / Clang types.

@adrian-prantl
Copy link
Contributor Author

@augusto2112 For some reason github did not let me request a review from you.

@adrian-prantl
Copy link
Contributor Author

Some more context: I'm working on a TypeRef-based Swift context for LLDB. Because we do not have reflection metadata for pure C types in Swift, reflection cannot compute TypeInfo for NominalTypeRefs for those types. By providing this callback, LLDB can supply this information for DWARF, and reflection can compute TypeInfos for mixed Swift/C types.

@slavapestov
Copy link
Contributor

For pure C types that are referenced from code, we emit BuiltinTypeDescriptors in IRGen. I'm guessing here you need the callback because expression evaluation can pull in arbitrary C types that are not referenced from code? If so this approach sounds great.

I have reservations about adding this to MemoryReader since it's not really about reading memory. Maybe we need a second callback interface, or would that be too awkward to plumb through?

@@ -623,7 +623,7 @@ class ReflectionContext

// Perform layout
if (start)
TI = TC.getClassInstanceTypeInfo(TR, *start);
TI = TC.getClassInstanceTypeInfo(TR, *start, getReader());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why I think a different callback would be nice. In theory it should be possible to look up TypeInfos without a remote process attached; and you could still have a callback to get C type info.

if (ThickFunctionTI != nullptr)
return ThickFunctionTI;

RecordTypeInfoBuilder builder(*this, RecordKind::ThickFunction);
builder.addField("function", getThinFunctionTypeRef());
builder.addField("context", getNativeObjectTypeRef());
builder.addField("function", getThinFunctionTypeRef(), reader);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't need a reader. A thick function is just a pair of pointers as far as RemoteMirrors are concerned.

@@ -1176,12 +1180,12 @@ class ExistentialTypeInfoBuilder {
// Class existentials consist of a single retainable pointer
// followed by witness tables.
if (Refcounting == ReferenceCounting::Unknown)
builder.addField("object", TC.getUnknownObjectTypeRef());
builder.addField("object", TC.getUnknownObjectTypeRef(), reader);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these should need to read imported TypeInfo either

// to instantiate a dummy reader here. This helps preserving the
// layering.
remote::MemoryReader dummyReader;
auto *SuperclassTI = TC.getTypeInfo(Superclass, dummyReader);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the reader parameter to getTypeInfo() be a pointer instead, with handing of the null case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe llvm:Optional to make it clear the reader is... well... optional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe llvm::Optional also has the benefit of being able to keep queryDataLayout, getSymbolAddress and readString deleted in the base class.

@augusto2112
Copy link
Contributor

@augusto2112 For some reason github did not let me request a review from you.

Probably because I'm not a project member (that's why I have to @ people when I want a review).

@adrian-prantl
Copy link
Contributor Author

For pure C types that are referenced from code, we emit BuiltinTypeDescriptors in IRGen. I'm guessing here you need the callback because expression evaluation can pull in arbitrary C types that are not referenced from code? If so this approach sounds great.

Interesting! The case I primarily debugged this with was using a type referenced in the code, but perhaps the example program was too simple to trigger emission of the metadata. I'll look into that — but it also seems like this could be useful even if that were a bug because of the pulling-extra-types-in scenario you mentioned.

I have reservations about adding this to MemoryReader since it's not really about reading memory. Maybe we need a second callback interface, or would that be too awkward to plumb through?

That sounds totally reasonable, I'll take a look at how well that fit.

@adrian-prantl
Copy link
Contributor Author

I inspected the LLVM IR generated for my testcase and there is no mention of the imported C type outside of debug info. When adding a print() of a variable of that type to the program, this changes. From that I'm concluding that the compiler will only emit the type metadata when there is an actual dependency on it. So it looks like I'm going to need this mechanism regardless.

@slavapestov
Copy link
Contributor

slavapestov commented Aug 12, 2020

I see, you're right. The compiler only emits the builtin descriptor when the type appears as the field type of another type, because the original use case for RemoteMirrors was to enable object graph debugging. It's reasonable to pull in additional type info for the types of local variables and such using the callback.

@adrian-prantl
Copy link
Contributor Author

I have now created a new swift::remote::TypeInfoProvider interface that is to be passed in on a per-function basis rather than owned by the TypeConverter. This actually helps removing some ugly statefulness in the LLDB patch using this.

@adrian-prantl adrian-prantl force-pushed the 55412920 branch 3 times, most recently from 757c094 to 203923e Compare August 20, 2020 22:05
… provide

swift::reflection::TypeInfo for (Clang-)imported non-Objective-C types. This is
needed to reflect on the size mixed Swift / Clang types, when no type metadata
is available for the C types.

This is a necessary ingredient for the TypeRef-based Swift context in
LLDB. Because we do not have reflection metadata for pure C types in Swift,
reflection cannot compute TypeInfo for NominalTypeRefs for those types. By
providing this callback, LLDB can supply this information for DWARF, and
reflection can compute TypeInfos for mixed Swift/C types.
@adrian-prantl
Copy link
Contributor Author

@slavapestov The LLDB side of this is ready now. Can you check if I addressed all your concerns?

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only have one last suggestion. I think we should stick the TypeInfoProvider inside the TypeConverter, so that it doesn't have to be passed around. What do you think?

@adrian-prantl
Copy link
Contributor Author

I think we should stick the TypeInfoProvider inside the TypeConverter, so that it doesn't have to be passed around.

My understanding is that swift::reflection::ReflectionContext owns exactly one Builder, which owns exactly one TypeConverter. LLDB, however, has one TypeInfoProvider per lldb::Module (≈ dylib) to localize type lookup, and one ReflectionContext per process. That's why it's passed in explicitly.

@shahmishal shahmishal closed this Sep 3, 2020
@slavapestov
Copy link
Contributor

I didn't realize we had one TypeInfoProvider per Module. In that case, I think it's fine to do what you're doing now (but we could also investigate having one TypeConverter per module or something?).

@shahmishal shahmishal reopened this Sep 3, 2020
@shahmishal
Copy link
Member

@adrian-prantl This PR need to be updated to target master branch form master-rebranch.

@adrian-prantl
Copy link
Contributor Author

@swift-ci test

@adrian-prantl adrian-prantl changed the base branch from master-rebranch to master September 3, 2020 02:40
@adrian-prantl
Copy link
Contributor Author

@swift-ci test

@swift-ci
Copy link
Contributor

swift-ci commented Sep 3, 2020

Build failed
Swift Test Linux Platform
Git Sha - 56b2e90

@swift-ci
Copy link
Contributor

swift-ci commented Sep 3, 2020

Build failed
Swift Test OS X Platform
Git Sha - 56b2e90

@adrian-prantl
Copy link
Contributor Author

@swift-ci smoke test

2 similar comments
@adrian-prantl
Copy link
Contributor Author

@swift-ci smoke test

@adrian-prantl
Copy link
Contributor Author

@swift-ci smoke test

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci test

@swift-ci
Copy link
Contributor

swift-ci commented Sep 4, 2020

Build failed
Swift Test Linux Platform
Git Sha - 56b2e90

@swift-ci
Copy link
Contributor

swift-ci commented Sep 4, 2020

Build failed
Swift Test OS X Platform
Git Sha - 56b2e90

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci smoke test

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci test

@swift-ci
Copy link
Contributor

swift-ci commented Sep 4, 2020

Build failed
Swift Test OS X Platform
Git Sha - 56b2e90

@swift-ci
Copy link
Contributor

swift-ci commented Sep 4, 2020

Build failed
Swift Test Linux Platform
Git Sha - 56b2e90

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci smoke test

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci test

@swift-ci
Copy link
Contributor

swift-ci commented Sep 5, 2020

Build failed
Swift Test Linux Platform
Git Sha - 56b2e90

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci test

@adrian-prantl
Copy link
Contributor Author

test with swiftlang/llvm-project#1636
@swift-ci smoke test

@adrian-prantl adrian-prantl merged commit 4247b60 into swiftlang:master Sep 8, 2020
@compnerd
Copy link
Member

compnerd commented Sep 9, 2020

@adrian-prantl this seems to have caused a regression on the Windows builds :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants