This is an archive of the discontinued LLVM Phabricator instance.

Prevent MDNode's RAUW from introducing a reference to a void Value.
ClosedPublic

Authored by friss on Oct 16 2014, 8:58 AM.

Details

Summary

It seems this isn't allowed: the IR dumper would render it as !{void <badref>}
and it would assert when serialized to bitcode.

The specifc case that triggers the wrong behavior is related to debug
information (as shown in the testcase), but the fix is in the general metadata
code.

Diff Detail

Repository
rL LLVM

Event Timeline

friss updated this revision to Diff 15022.Oct 16 2014, 8:58 AM
friss retitled this revision from to Prevent MDNode's RAUW from introducing a reference to a void Value..
friss added reviewers: echristo, dblaikie.
friss updated this object.
friss added a subscriber: Unknown Object (MLST).
echristo edited edge metadata.Oct 16 2014, 1:02 PM

How'd we get the void anyhow?

friss added a comment.Oct 16 2014, 3:54 PM

If you look at the added testcase, it cast a void (*func)() to a int (*func)(). The int typed result is referenced in a debug info metadata node (an argument to the dbg.value intrinsic). Then instcombine would remove the bitcast and turn the int returning function into a void returning function that gets RAUWd over the value in the MDNode. And at this point in the current code you have invalid IR.

The code in the testcase is reduced from a huge LTO link that encountered this situation in a much more complicated setup.

friss updated this revision to Diff 15261.Oct 22 2014, 10:50 AM
friss edited edge metadata.

New try to fix this issue with a different stategy: add an assert to enforce
that ValueHandleBase::ValueIsRAUWd isn't called with a new value that hasn't
the same type as the old one. Fix InstCombine to not violate the invariant.

How does that look?

dblaikie edited edge metadata.Oct 22 2014, 11:01 AM

Generally looks OK - but I'll leave it to someone more confident with the ValueHandle, RAUW, etc semantics to sign off on.

Ideally I'd probably like a more valid test case as, if we optimize away this scenario at some point the test case might become invalid (either testing parts of instcombine we don't actually ever need it to handle, or maybe instcombine would just eliminate such instructions - in which case this test case would no longer be testing this codepath, for example)

Actually I should be able to easily extend the testcase to include a valid call to a bitcasted function type also (the fix changed scope, and the new one should be easier to test). I'd like to leave the UB call there for now as it is the initial issue that I chased, the one that caused an assert during bitcode serialization.

friss added a comment.Oct 22 2014, 1:56 PM

Seems I was wrong about being able to extend the testcase. Changing the scope of the fix didn't change the fact that I need a constant bitcast inside a call to trigger that code path. And I'm not able to produce this without resorting to UB at the C level.

Unless you have another idea, I think I'll commit the test I have.

In D5828#10, @friss wrote:

Seems I was wrong about being able to extend the testcase. Changing the scope of the fix didn't change the fact that I need a constant bitcast inside a call to trigger that code path. And I'm not able to produce this without resorting to UB at the C level.

Unless you have another idea, I think I'll commit the test I have.

Nope, no particular ideas short of mucking with the assertion (perhaps so it triggers on anything other than this case) & running over a selfhost or other corpus to see if anything more realistic/reasonable/future-proof crops up.

Not a requirement, just a desire/preference if it were possible/practical.

friss closed this revision.Oct 22 2014, 9:19 PM
friss updated this revision to Diff 15298.

Closed by commit rL220468 (authored by @friss).