This is an archive of the discontinued LLVM Phabricator instance.

Promote NPCs used as arguments to variadic functions
ClosedPublic

Authored by rnk on Sep 24 2014, 9:16 AM.

Details

Summary

Make it possible to pass NULL through variadic functions on platforms
where NULL has an integer type that is more narrow than a pointer. On
such platforms we widen null pointer constants to a pointer-sized
integer.

Fixes PR20949.

Diff Detail

Repository
rL LLVM

Event Timeline

rnk updated this revision to Diff 14038.Sep 24 2014, 9:16 AM
rnk retitled this revision from to Promote NPCs used as arguments to variadic functions.
rnk updated this object.
rnk added reviewers: thakis, rsmith.
rnk added a comment.Sep 24 2014, 9:24 AM

Note that Linux headers sometimes define NULL to 0 on x86_64, which causes the same problem. This change will "fix" the problem by widening the int to an intptr_t.

thakis accepted this revision.Sep 24 2014, 9:30 AM
thakis edited edge metadata.

lgtm, thanks!

For 32bit, this should never make a difference in practice. For 64bit, passing "0" to a varargs function will now be a 8 byte write instead of a 4 byte write, but arguments are 8-byte aligned there, and nothing should break if the padding bytes for 0s are now zero instead of random (and for pointers, it helps).

This revision is now accepted and ready to land.Sep 24 2014, 9:30 AM
rnk edited edge metadata.Sep 24 2014, 9:47 AM
rnk added a subscriber: Unknown Object (MLST).

Woops, forgot to cc cfe-commits.

It's usually best to throw out a Phab review & start again if you don't cc
a mailing list when you first create it. (because phab won't re-send the
original mail - which means the mailing list has no context (no patch
description and more importantly, not attached patch))

rnk updated this revision to Diff 14050.Sep 24 2014, 1:46 PM
  • Move changes to CodeGen

Perhaps a warning should be added so code doesn't "miscompile" when compiled with GCC?

Is there a reason to restrict this just to null pointer constants?

lib/CodeGen/CGCall.cpp
2601 ↗(On Diff #14050)

This should be removed.

rnk added a comment.Oct 2 2014, 2:22 PM
In D5480#13, @majnemer wrote:

Perhaps a warning should be added so code doesn't "miscompile" when compiled with GCC?

I don't think the warning is actionable for the user. How do we avoid false positives on printf("%d\n", 0)?

Users are typically saavy enough to know that passing '0' to a varargs function will be interpreted as an int, or at least be able to debug the crash once it happens. The subtle case is when passing NULL, which 99% of the time just works with GCC's stddef.h. In the 1% corner case where NULL is defined incorrectly (literal 0 and not 0L), I can live the fact that clang and gcc will have subtle behavior differences.

Is there a reason to restrict this just to null pointer constants?

I don't see why we should implicitly widen all ints to i64 in varargs contexts.

rnk updated this revision to Diff 14349.Oct 2 2014, 2:25 PM

remove errs

rsmith edited edge metadata.Oct 7 2014, 5:08 PM

I wonder whether it makes sense to restrict this to 64-bit MSVC platforms, since it's not really a problem elsewhere (other platforms have a sane NULL) and it presumably generates marginally worse code. Plus if we start doing this on, say, Mac OS, it'll make it harder for people to spot they have a bug until they port to another system.

lib/CodeGen/CGCall.cpp
2721 ↗(On Diff #14349)

Is there any way we can check that the current target permits this? (That is, that widening an integer argument to pointer width will never change the calling convention.)

3024 ↗(On Diff #14349)

Could just CreateZExt here. Presumably we should never coerce to a narrower type?

rnk added a comment.Oct 9 2014, 11:50 AM
In D5480#19, @rsmith wrote:

I wonder whether it makes sense to restrict this to 64-bit MSVC platforms, since it's not really a problem elsewhere (other platforms have a sane NULL) and it presumably generates marginally worse code. Plus if we start doing this on, say, Mac OS, it'll make it harder for people to spot they have a bug until they port to another system.

OK, but there are other triples (WoA) that use the itanium environment that might have broken headers, so how about Windows platforms where pointer size != integer size? (aarch64, x86_64, ppc64)

lib/CodeGen/CGCall.cpp
2721 ↗(On Diff #14349)

There is no such predicate currently. I don't think there is value in adding a predicate which will always return true for all current targets.

3024 ↗(On Diff #14349)

Sure.

rnk updated this revision to Diff 14674.Oct 9 2014, 1:38 PM
rnk edited edge metadata.
  • Restrict it to windows.
rsmith accepted this revision.Oct 9 2014, 4:03 PM
rsmith edited edge metadata.

LGTM

test/CodeGenCXX/varargs.cpp
18–19 ↗(On Diff #14674)

The comment is a lie...

rnk closed this revision.Oct 9 2014, 5:16 PM
rnk updated this revision to Diff 14689.

Closed by commit rL219456 (authored by @rnk).