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.
Details
Diff Detail
Event Timeline
lib/IR/Globals.cpp | ||
---|---|---|
103–110 | I find it a little weird that we are trying to predict how the global will be used. 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? |
lib/IR/Globals.cpp | ||
---|---|---|
103–110 |
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).
...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...
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.
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...
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.
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.
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?