This is an archive of the discontinued LLVM Phabricator instance.

Introduce the idea of a minimum libc version
Needs ReviewPublic

Authored by compnerd on Feb 14 2015, 9:23 AM.

Details

Reviewers
rnk
Summary

Add the -mmin-libc-version= flag to the driver and encode this into the module
level metadata. This will permit the backend to make certain code generation
choices with the knowledge that the target code will run on a minimum libc
version.

On Windows, this will enable us to enable a number of C99 math routines that are
available in MSVCRT 12.0+, though this is certainly not limited to Windows.
There have been cases where code generation on the Linux targets could do
something slightly different if it knew what version of libc it was targeting.

The module level metadata is needed to ensure that LTO does not break down.
When combining modules targeting differing minimum version, the selection of the
highest version should prevail (since older versions should work on newer, but
not vice-versa).

Diff Detail

Repository
rL LLVM

Event Timeline

compnerd updated this revision to Diff 19966.Feb 14 2015, 9:23 AM
compnerd retitled this revision from to Introduce the idea of a minimum libc version.
compnerd updated this object.
compnerd edited the test plan for this revision. (Show Details)
compnerd added a reviewer: rnk.
compnerd set the repository for this revision to rL LLVM.
compnerd added subscribers: Unknown Object (MLST), danalbert.

Er, I don't see how "libc version" is a meaningful thing on linux. The presumption of which libc implementation is not baked into the triple.

-gnu implies GLIBC. Traditionally, -uclibc is used instead of -gnu for uclibc environments, and many (most?) Linux distros use -musl to indicate a MUSL environment. For Android, the environment is -android, and thus, assumed to be bionic. If the OS is BSD, usually, the assumption is that it is using the BSD libc. I guess that we can disable this for Linux, but I think that this would be useful to have for non-Windows environments, particularly Android, where you do have differences between versions (IIRC L fixed issues with PIC).

We already support a version for the environment in the triple, can we just use that?

Yes, we *could*. Its just a matter of how it is being specified. I find that having the separate option is potentially cleaner than stuffing it in the triple (which does get pushed into the metadata), and then parsing it back out as a value. I think that this is something that longer term could be more easily merged into some of the ideas floated about on the thread regarding the future of triples. Is there a strong reason to stuff this into the triple and parse it back out?

I think it would be inconsistent with the other platforms which have this version information. The platforms which have an environment version stick it in the triple (Android, MSVC) and the platforms which have an OS version also stick it in the triple (Darwin, iOS, OS X).

Furthermore, it is possible to specify the MSVC version and the Darwin OS version in clang without specifying the entire triple. The -fms-compatibility-version flag (and the corresponding flags for Darwin-based operating systems) update the version.

Okay, if thats the general pattern, then we can stick it in the triple. Though, that means that the use of the triple for determining the MS compatibility needs to be undone. If the version in the triple is the libc version, then it can differ from the MS compatibility version. The target platform may be different from the compiler version (IIRC, thats the terminology that Visual Studio uses).

Okay, if thats the general pattern, then we can stick it in the triple. Though, that means that the use of the triple for determining the MS compatibility needs to be undone. If the version in the triple is the libc version, then it can differ from the MS compatibility version. The target platform may be different from the compiler version (IIRC, thats the terminology that Visual Studio uses).

Before VS 2013, Visual C++ shiped a msvcrt and compiler in tandem which would mean that the version of the compiler and library should be the same, no?

After VS 2013, things get a bit more confusing. There is ucrt which lives in the PSDK + msvcrt which lives in the MSVC SDK.

If I understand things correctly, the following are true:

  • ucrt forms a stable interface, no exported functions can be removed
  • ucrt could, in theory, grow additional functionality
  • msvcrt will continue to change but must assume a base line ucrt, it might have to work with the ucrt included with Windows 10 many years after the fact

AFAICT, the compiler is only concerned about the version-to-version contents of msvcrt and not ucrt because ucrt is essentially unchanging. This indicates, to me, that we are still concerned with the compiler version.

AIUI, ucrt is absolutely relevant since msvcrt itself has been split out into the ucrt. msvcrt is the "shared" common bits, while the ucrt is more "platform" specific bits.

But really, the point is: supporting an older version with a newer compiler is what doing this the way I suggest enables. You can use a newer compiler but still allow the generated binary to target an alternative environment.

rnk edited edge metadata.Aug 13 2015, 7:06 PM
rnk added a subscriber: rnk.

We could support that by allowing the MSVC version in the triple to be
different from the -fms-compatibility-version on the command line. Today,
this might even with with --target.

That said, I don't imagine many people are doing this. Microsoft makes it
hard for you to do this, and lots of code assumes that the _MSC_VER macro
correlates with the CRT version.

AIUI, ucrt is absolutely relevant since msvcrt itself has been split out into the ucrt. msvcrt is the "shared" common bits, while the ucrt is more "platform" specific bits.

But really, the point is: supporting an older version with a newer compiler is what doing this the way I suggest enables. You can use a newer compiler but still allow the generated binary to target an alternative environment.

Er, I see it a bit differently. UCRT is the boring, unchanging part of the CRT which is supposed to provide binary compatibility across versions. It has everything it needs to make junk like FILE * stable through time and the definition of fopen. AFAICT, UCRT provides functionality equivalent to C99 + some random MS-specific stuff.

Correct me if I'm wrong but VS 2013 seemed to have provided all of the functions that TLI cares about and 2015 refactored those functions into UCRT. The UCRT's interface can never shrink which means we can rely on this support indefinitely for all future versions of _MSC_VER.

I think an argument could be made if we believed it to be likely that further interesting library functionality might be exposed through UCRT that the compiler might care about. I'd rather cross that bridge when we get there.