Skip to content

[irgen] Force emission of objc class refs for non-foreign clang objc classes whose metadata we use. #28174

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

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Nov 9, 2019

Today in far more cases we are using mangled strings to look up metadata at
runtime. If we do this for an objc class but for whatever reason we do not have
any other references to the class, the static linker will fail to link in the
relevant framework. The reason why this happens is that autolinking is treated
by the static linker as a hint that a framework may be needed rather than as a
"one must link against the framework". If there aren't any undefined symbols
needed by the app from that framework, the linker just will ignore the hint. Of
course this then causes the class lookup to fail at runtime when we use our
mangled name to try to lookup the class.

I included an Interpreter test as well as IRGen tests to make sure that we do
not regress here in the future.

NOTE: The test modifications here are due to my moving the ObjCClasses framework
out of ./test/Interpreters/Inputs => test/Inputs since I am using it in the
IRGen test along side the interpreter test.

rdar://56136123

@gottesmm gottesmm requested review from jckarter and rjmccall November 9, 2019 02:00
@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

@rjmccall what do you think of the query here? Would you change anything?

@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

@swift-ci test

@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

I am probably going to add to the FileCheck pattern in the IRGen test that the class ref is marked no dead strip (which it is today).

@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

but I am going to do that in a follow on commit.

@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

*I mean I am going to do it after the full test passes so I can just smoke test.

@rjmccall
Copy link
Contributor

rjmccall commented Nov 9, 2019

It's quite unfortunate that we have to emit a bunch of symbol references which are likely to have real load-time costs just to get something linked in. If this is just a short-term solution, okay, but can we figure out a longer-term solution that would force the library to be linked?

Actually, that has immediate implications as well, since we can't always a class ref for an imported class (e.g. if it's a runtime-only class).

@@ -1252,13 +1252,34 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
return;

// Force emission of ObjC protocol descriptors used by type refs.
if (auto proto = dyn_cast<ProtocolDecl>(type)) {
if (auto *proto = dyn_cast<ProtocolDecl>(type)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Spurious change?

@@ -1252,13 +1252,34 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
return;

// Force emission of ObjC protocol descriptors used by type refs.
if (auto proto = dyn_cast<ProtocolDecl>(type)) {
if (auto *proto = dyn_cast<ProtocolDecl>(type)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Spurious change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just a small thing I noticed. If it really bugs you I can remove it.

Copy link
Contributor

Choose a reason for hiding this comment

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

It just doesn't seem like an improvement in any way. Also, I have several times had to go through and fix a bunch of places where somebody needlessly recorded that something was a pointer only for a refactor to start encapsulating it in a class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok.

@gottesmm
Copy link
Contributor Author

gottesmm commented Nov 9, 2019

@rjmccall For a longer term solution, we would have to change the guarantees that the static linker provides around autolinking. We would need autolinking to not be a suggestion, but a hard requirement.

@swift-ci
Copy link
Contributor

swift-ci commented Nov 9, 2019

Build failed
Swift Test OS X Platform
Git Sha - 949de9ed5223c471bda15ad2a59437463067cfc8

@gottesmm
Copy link
Contributor Author

Just for anyone listening in, @rjmccall and I talked about this offline and we agreed to wait a second to talk with @DougGregor when he is back in the office tomorrow.

@gottesmm
Copy link
Contributor Author

@rjmccall, @DougGregor, and I talked about this offline and we agree that in the short term this is the appropriate step to take.

…classes whose metadata we use.

Today in far more cases we are using mangled strings to look up metadata at
runtime. If we do this for an objc class but for whatever reason we do not have
any other references to the class, the static linker will fail to link in the
relevant framework. The reason why this happens is that autolinking is treated
by the static linker as a hint that a framework may be needed rather than as a
"one must link against the framework". If there aren't any undefined symbols
needed by the app from that framework, the linker just will ignore the hint. Of
course this then causes the class lookup to fail at runtime when we use our
mangled name to try to lookup the class.

I included an Interpreter test as well as IRGen tests to make sure that we do
not regress here in the future.

NOTE: The test modifications here are due to my moving the ObjCClasses framework
out of ./test/Interpreters/Inputs => test/Inputs since I am using it in the
IRGen test along side the interpreter test.

rdar://56136123
@gottesmm gottesmm force-pushed the pr-7bbd01cc86ac04db4e31ad2128d842d7205d3314 branch from 949de9e to 8247525 Compare November 22, 2019 00:04
@gottesmm
Copy link
Contributor Author

@swift-ci test

3 similar comments
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm gottesmm merged commit 79444c4 into swiftlang:master Nov 22, 2019
@gottesmm gottesmm deleted the pr-7bbd01cc86ac04db4e31ad2128d842d7205d3314 branch November 22, 2019 02:37
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.

3 participants