This is an archive of the discontinued LLVM Phabricator instance.

Fix cloning GlobalValues with comdats across Modules.
AbandonedPublic

Authored by jlebar on Jun 10 2016, 7:07 PM.

Details

Reviewers
majnemer
rnk
Summary

Previously copyAttributesFrom would copy the Comdat pointer from one
GlobalValue to another. The Comdat is owned by the Module, so if the
two GlobalValues were not in the same module, this would be Bad.

Diff Detail

Event Timeline

jlebar updated this revision to Diff 60433.Jun 10 2016, 7:07 PM
jlebar retitled this revision from to Fix cloning GlobalValues with comdats across Modules..
jlebar updated this object.
jlebar added reviewers: rnk, majnemer.
jlebar added a subscriber: llvm-commits.
jlebar updated this revision to Diff 60554.Jun 13 2016, 9:50 AM

Add missing null check.

jlebar updated this revision to Diff 60556.Jun 13 2016, 10:25 AM

Preserve old behavior when a function isn't in a module.

Now all the tests pass. :)

majnemer added inline comments.Jun 13 2016, 10:38 AM
lib/IR/Globals.cpp
103–110

I find it a little weird that we are trying to predict how the global will be used.
We are not sure which module it will be in but we sorta assume it will be in the same one as the original function...

I'm starting to think that the right thing to do is move this logic out of copyAttributesFrom and into another method. Something like copyComdatFrom which asserts that the source and dest are from the same module.

What do you think?

jlebar added inline comments.Jun 13 2016, 10:44 AM
lib/IR/Globals.cpp
103–110

I find it a little weird that we are trying to predict how the global will be used.

Me too.

An alternative would be not to set the comdat at all if the function isn't in a module. That's how I originally had it, but it broke a test (which was what made me realize it was a functional change in the first place).

Something like copyComdatFrom which asserts that the source and dest are from the same module.

...or maybe it would assert that just that src and dst are both in a module, and then copy the comdat as we do here? That seems like basically what one would want, I think.

The problem with adding either of these new functions is that we'd have to audit the ~30 calls to copyAttributesFrom, and I'm not sure I'm going to be successful at that.

Something like copyComdatFrom which asserts that the source and dest are from the same module.

What are the circumstances under which one would or wouldn't want to copy the comdat, when copying all the rest of the attributes? Like, if we should (almost) always do it, then moving it into a separate function doesn't make a lot of sense to me. OTOH if we almost never actually want do it...

rnk edited edge metadata.Jun 15 2016, 8:38 AM

I think most users of copyAttributesFrom are not copying globals across modules, they are trying to RAUW in the current module. The one user that I know of (the IR linker) goes out of its way to copy the comdat separately. Anything wrong with forcing the cross-module use case to be a little more complicated? Such users already have to rewrite the initializer to avoid cross-module references, so rewriting the comdat as well isn't that crazy.

In D21255#458782, @rnk wrote:

Anything wrong with forcing the cross-module use case to be a little more complicated?

I guess the suggestion is,

  • leave the implementation of copyAttributesFrom alone, and
  • add a comment explaining what needs to be done if you're copying between modules?

I guess I'm fine with that, although given that we already had a nontrivial bug (that took me half a day to track down), I am a bit concerned about leaving the footgun there as-is. Even if all of the code in llvm is correct, this seems like a pretty sharp edge to expose to future authors.

What if we modified Function::setParent to either

  • assert that the comdat is from the right module, or
  • fix up the comdat?

I guess if cross-module copiers have to fix up the initializers, an assertion might be the most appropriate thing, but I'm fine with either.

rnk added a comment.Jun 15 2016, 10:45 AM
In D21255#458782, @rnk wrote:

Anything wrong with forcing the cross-module use case to be a little more complicated?

I guess the suggestion is,

  • leave the implementation of copyAttributesFrom alone, and
  • add a comment explaining what needs to be done if you're copying between modules?

I guess I'm fine with that, although given that we already had a nontrivial bug (that took me half a day to track down), I am a bit concerned about leaving the footgun there as-is. Even if all of the code in llvm is correct, this seems like a pretty sharp edge to expose to future authors.

What if we modified Function::setParent to either

  • assert that the comdat is from the right module, or
  • fix up the comdat?

I guess if cross-module copiers have to fix up the initializers, an assertion might be the most appropriate thing, but I'm fine with either.

Yeah, it is pretty crummy. I think this is why David didn't copy the comdat with the other attributes in the first place.

I like the idea of asserting in setParent. We don't currently do the analogous check for GlobalVariable initializers, but we should consider it. :)

I like the idea of asserting in setParent

Okay, this doesn't quite work. You can assert in setParent, but it doesn't make sense to assert there but not inside copyAttributesFrom. But if we assert in copyAttributesFrom, that means that the IRLinker needs to be changed so that the GlobalValue it copies into is not in a module. And changing that looks nontrivial (and contrived).

I guess we could leave the assertion in place and add a new function, copyAttributesExceptComdatFrom. We'd have to make this one virtual and make copyAttributesFrom non-virtual. Not sure how I feel about that...

majnemer edited edge metadata.Jun 15 2016, 12:28 PM

I like the idea of asserting in setParent

Okay, this doesn't quite work. You can assert in setParent, but it doesn't make sense to assert there but not inside copyAttributesFrom. But if we assert in copyAttributesFrom, that means that the IRLinker needs to be changed so that the GlobalValue it copies into is not in a module. And changing that looks nontrivial (and contrived).

I guess we could leave the assertion in place and add a new function, copyAttributesExceptComdatFrom. We'd have to make this one virtual and make copyAttributesFrom non-virtual. Not sure how I feel about that...

How about let's just remove the COMDAT machinations from copyAttributesFrom. Maybe provide another mechanism for comdats.

rnk added a comment.Jun 15 2016, 12:50 PM

How about let's just remove the COMDAT machinations from copyAttributesFrom. Maybe provide another mechanism for comdats.

For non-module copying, it's only a one liner, so sure, let's revert http://reviews.llvm.org/D20631.

jlebar abandoned this revision.Jun 15 2016, 1:14 PM

For non-module copying, it's only a one liner, so sure, let's revert http://reviews.llvm.org/D20631.

OK, I'll send you a patch.