Skip to content

[lldb] Add ReferenceTypeInfo support to SwiftLanguageRuntimeImpl::GetNumChildren #2218

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

Conversation

kastiglione
Copy link

@kastiglione kastiglione commented Dec 10, 2020

Add ReferenceTypeInfo support to SwiftLanguageRuntimeImpl::GetNumChildren. This uses TypeConverter::getClassInstanceTypeInfo to get a RecordTypeInfo for a class. And uses TypeRefBuilder::lookupSuperclass to determine if a class has a superclass (base class).

rdar://68171335

@@ -997,6 +997,38 @@ llvm::Optional<uint64_t> SwiftLanguageRuntimeImpl::GetMemberVariableOffset(
return offset;
}

static CompilerType GetWeakReferent(TypeSystemSwiftTypeRef &ts,
Copy link
Author

Choose a reason for hiding this comment

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

this whole function was moved up and nothing more.

Comment on lines +81 to +82
GetTypeInfo(CompilerType type, ExecutionContextScope *exe_scope,
swift::reflection::TypeRef const **out_tr = nullptr);
Copy link
Author

Choose a reason for hiding this comment

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

Added an out parameter to return the typeref.

Choose a reason for hiding this comment

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

It might be cleaner to factor out a function

const swift::reflection::TypeInfo *GetTypeInfo(swift::reflection::TypeRef type_ref)

and call that directly where we need the type_ref? If it isn't, then returning either a std::pair<> or a struct {TypeInfo type_info; TypeRef type_ref} may be more elegant.

@kastiglione kastiglione marked this pull request as draft December 10, 2020 01:54
@kastiglione
Copy link
Author

Initial draft for availability/review, haven't done tests yet.

@kastiglione
Copy link
Author

TODO

  • Figure out what value to use for start parameter of getClassInstanceTypeInfo

auto *reflection_ctx = GetReflectionContext();
auto tc = swift::reflection::TypeConverter(reflection_ctx->getBuilder());
LLDBTypeInfoProvider tip(*this, *ts);
auto *cti = tc.getClassInstanceTypeInfo(tr, 0, &tip);
Copy link
Author

Choose a reason for hiding this comment

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

I have a todo to figure out if other values should be used instead of 0 for start.

Copy link
Author

Choose a reason for hiding this comment

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

The tests pass, and no SwiftASTContext validations fail when using start = 0. I'll learn more about this field before merging, but I don't think it's an issue.

Choose a reason for hiding this comment

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

Sounds good.

auto *cti = tc.getClassInstanceTypeInfo(tr, 0, &tip);
if (auto *rti =
llvm::dyn_cast_or_null<swift::reflection::RecordTypeInfo>(cti)) {
return rti->getNumFields();

Choose a reason for hiding this comment

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

Should this be a recursive case or will there only ever be a record type underneath a class? (Well, probably).

Copy link
Author

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

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

We could factor out a helper function GetNumFieldsFromTypeInfo() that calls itself here, but the savings are marginal.

Copy link
Author

Choose a reason for hiding this comment

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

I'll soon be implementing GetNumFields, and which may call for some refactoring.

I have a question, by "calls itself" do you mean recursive like in your top comment? If so, can you elaborate on what needs to be recursive?

if (!tr)
return {};

auto *reflection_ctx = GetReflectionContext();

Choose a reason for hiding this comment

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

Would this fit nicely into one case in the switch above, or are there many different kinds for which this path makes sense?

Copy link
Author

Choose a reason for hiding this comment

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

good question, I'm not sure yet. Once this PR is working, I'll compare the paths then.

Copy link
Author

Choose a reason for hiding this comment

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

What do you think? There are a couple distinct conditions in each case that don't make sense to the other case, and so combing the two doesn't feel like a no-brainer to me.

Choose a reason for hiding this comment

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

I was just thinking of writing this as

    switch (rti->getReferenceKind()) {
     case swift::reflection::ReferenceKind::Weak:
     case swift::reflection::ReferenceKind::Unowned:
     case swift::reflection::ReferenceKind::Unmanaged:
       // Weak references are implicitly Optionals, so report the one
       // child of Optional here.
       if (GetWeakReferent(*ts, type))
         return 1;
       break;
     default: {
       if (!tr)
         return {};
       auto tc = swift::reflection::TypeConverter(reflection_ctx->getBuilder());
....

but that's purely cosmetic and not important at all...

Copy link
Author

Choose a reason for hiding this comment

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

thanks, I had misunderstood. I will make that change in a follow up.

@kastiglione
Copy link
Author

Currently one kind of test failure is with subclasses: GetNumChildren is off by one because it's not taking into account the child that represents the superclass. I'll need to figure out how determine whether the ReferenceTypeInfo has a parent class.

Another test failure is something I mentioned in #2200, that TypeRef's can expose private fields even when compiling with library evolution and .swiftinterfaces. By implementing this, it seems to have unlocked GetCompilerChildAtIndex to return private variables, so those tests will need to be updated.

@adrian-prantl
Copy link

Currently one kind of test failure is with subclasses: GetNumChildren is off by one because it's not taking into account the child that represents the superclass. I'll need to figure out how determine whether the ReferenceTypeInfo has a parent class.

Maybe you can reuse some of the code used in GetChildCompilerTypeAtIndex for this (although it does start out from an instance pointer).

Another test failure is something I mentioned in #2200, that TypeRef's can expose private fields even when compiling with library evolution and .swiftinterfaces. By implementing this, it seems to have unlocked GetCompilerChildAtIndex to return private variables, so those tests will need to be updated.

That's actually a good thing and precisely what we need in order for Foundation value types to work!

@kastiglione
Copy link
Author

That's actually a good thing and precisely what we need in order for Foundation value types to work!

yes I was excited to see it!

@kastiglione
Copy link
Author

Maybe you can reuse some of the code used in GetChildCompilerTypeAtIndex for this (although it does start out from an instance pointer).

I figured I'd need a way to do it with just the reflection API (no instance), and I found NominalTypeRef::getParent, but it's null. I've asked some Swift folks to see if that's the right API, or if there's something else.

@kastiglione kastiglione marked this pull request as ready for review December 10, 2020 20:32
@kastiglione
Copy link
Author

@swift-ci test

@kastiglione
Copy link
Author

@swift-ci test

@kastiglione
Copy link
Author

Tests pass locally, hopefully CI too. Ready for review.

@kastiglione
Copy link
Author

Maybe you can reuse some of the code used in GetChildCompilerTypeAtIndex for this (although it does start out from an instance pointer).

To follow up here, TypeRefBuilder::lookupSuperclass was used to determine if there's a superclass. See 3ff1e49

Copy link

@adrian-prantl adrian-prantl left a comment

Choose a reason for hiding this comment

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

Functionally this LGTM. I have only cosmetic comments and those can also be addressed later.

@kastiglione
Copy link
Author

Thanks, I will do the cosmetic changes in a followup, primarily because I don't want to wait another full test cycle.

@kastiglione kastiglione merged commit a72a24c into swift/main Dec 11, 2020
@kastiglione kastiglione deleted the lldb-Add-ReferenceTypeInfo-support-to-SwiftLanguageRuntimeImpl-GetNumChildren branch December 11, 2020 01:30
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.

2 participants