[cfe-dev] new predefined macros to expose target triple values?

Saleem Abdulrasool via cfe-dev cfe-dev at lists.llvm.org
Sun Dec 3 10:14:38 PST 2017

On Fri, Dec 1, 2017 at 2:46 PM, Bob Wilson <bob.wilson at apple.com> wrote:

> On Dec 1, 2017, at 8:09 AM, Saleem Abdulrasool <compnerd at compnerd.org>
> wrote:
> On Thu, Nov 30, 2017 at 5:15 PM, Bob Wilson via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>> I wondering if anyone besides Apple would be interested in having
>> predefined macros to identify the target OS and environment.
>> Background: Over the last few years, Apple has added several new
>> platforms (tvOS and watchOS) as well as simulator variants for those, and
>> we’ve accumulated a fair bit of complexity by adding Clang support for
>> those platforms with a copy-and-paste approach. The -mmacosx-version-min
>> option worked well when there was only one Apple platform, but it’s not so
>> great now that we have a lot of -m*-version-min options. We’re trying to
>> move toward the more standard approach of using the -target option to
>> specify the target triple, including the OS version. Akira added support
>> for that earlier (Clang r307982) and we’ve started moving toward
>> identifying simulator targets via the environment field of the triple (LLVM
>> r316380). Related to that, we also need a way to identify via predefined
>> macros what target we’re building for. We recently added the
>> __APPLE_EMBEDDED_SIMULATOR__ macro to distinguish the simulator targets
>> (although it is currently not working when you use the -target option
>> alone), but we don’t have anything to distinguish iOS vs. tvOS vs. watchOS.
>> It occurred to me that we can do this in a very general way by exposing
>> the OS and Environment fields of the target triple directly in predefined
>> macros. (We could do the same for the Arch and Vendor fields if anyone has
>> a use for those.)
> +1 on this.
> Arch is exposed, although possibly with a different spelling (e.g.
> `__powerpc__`).  The vendor is also usually exposed in most toolchains
> (e.g. `__APPLE__`, or `__INTEL__` from ICC), but is not done in a
> generalized manner, and is something which I had intended to do as a
> cleanup.  If you can beat me to it, great!  The OS is already exposed (e.g.
> `__linux__`), but again suffers the problem of not being done in a
> generalized manner.
>> We could add these new macros only for Darwin targets, but since they are
>> not at all Darwin-specific, what do you all think of adding them for all
>> targets?
> I think all the targets is pretty reasonable.  This actually came up a
> while ago, but we never went down this path for libc++.  Right now, libc++
> is able to build with the itanium ABI and the Microsoft ABI on Windows.
> Differentiating which ABI we are using is currently not possible, but
> access to the environment would solve the problem.
> To be specific, here’s the change that I’m suggesting. (I’ll put it up for
>> a proper review with a testcase if there is positive feedback for doing it
>> this way.)
> Most of the triple is made accessible, the environment is the one piece
> which is not, and I think it would be nice to have a uniform way of
> inspecting this information.
> I believe that we could keep the existing architecture macros, uniformly
> expose vendor as `__<upper case vendor>__`.  The OS could be exposed
> uniformly as `__<lower case os>__`.  The environment, since there is no
> real precedent, we can bike shed (fuchsia seems to be a popular color these
> days :-p), but no strong opinions on that.  I believe if we expose the
> environment, all 9 pieces of the triple should be visible.
> This is different than what I was proposing here, but you made me realize
> the fatal flaw in my proposal: there isn’t a good way to do string
> comparisons in preprocessor conditionals. My thought was that we could
> write things like:
> #if __TARGET_ENVIRONMENT__ == simulator
> for code that is specific to the iOS simulator (for example), but of
> course that doesn’t work.

Yeah, its unfortunate that that pattern isn't really feasible.

> Alternatively, we could adopt a convention of prefixing the macro names
> with the triple component name, e.g.:
> etc.
> instead of the raw values:
> __TVOS__
> It would make sense to me to add the __TARGET-prefixed versions for all
> targets, but if we do the raw values I would be inclined to do them
> selectively for platforms that I understand and can test. I slightly prefer
> the prefixed versions — they give context to show that the macros are about
> the environment or OS. On the other hand, I suppose they would be a
> departure from the existing convention with macros like __APPLE__ and
> __ELF__.

I actually prefer the un-prefixed versions.  I can appreciate the
additional context, but, it would be rather grating from the perspective of
combining the old and new versions.  I could be convinced for the prefixed
environment macro as there isn't as strong of a precedent there (there is
only android which has an environment mapping macro that I can think of).


One other option is to provide a function-like macros to accomplish this.
Similar to `__has_feature`, we could expose:

- `__is_auxiliary_os(os)`
- `__is_target_os(os)`
- `__is_auxiliary_environment(environment)`
- `__is_target_environment(environment)`
- `__is_auxiliary_vendor(vendor)`
- `__is_target_vendor(vendor)`

This would be cleaner overall I feel, but a much more radical departure for
these cases.

> [arch][subarch][endian]-[vendor]-[os]-[environment][abi][object
> format][version]
>> diff --git lib/Frontend/InitPreprocessor.cpp
>> lib/Frontend/InitPreprocessor.cpp
>> index 67c1faddc3..c1dfb39c37 100644
>> --- lib/Frontend/InitPreprocessor.cpp
>> +++ lib/Frontend/InitPreprocessor.cpp
>> @@ -713,6 +713,14 @@ static void InitializePredefinedMacros(const
>> TargetInfo &TI,
>>    // Initialize target-specific preprocessor defines.
>> +  // Identify the OS and Environment fields of the target triple.
>> +  Builder.defineMacro("__TARGET_OS__",
>> +                      TI.getTriple().getOSTypeName(T
>> I.getTriple().getOS()));
>> +  if (TI.getTriple().hasEnvironment()) {
>> +    Builder.defineMacro("__TARGET_ENVIRONMENT__",
>> +      TI.getTriple().getEnvironmentTypeName(TI.getTriple().
>> getEnvironment()));
>> +  }
>> +
>>    // __BYTE_ORDER__ was added in GCC 4.6. It's analogous
>>    // to the macro __BYTE_ORDER (no trailing underscores)
>>    // from glibc's <endian.h> header.
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> --
> Saleem Abdulrasool
> compnerd (at) compnerd (dot) org

Saleem Abdulrasool
compnerd (at) compnerd (dot) org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20171203/0f586d82/attachment-0001.html>

More information about the cfe-dev mailing list