@@ -46,18 +46,21 @@ their parts) that are not portable, but it doesn't help if the system headers
4646are non-portable and not fixed. An alternative model that would be easy to use
4747is a 'tainting' scheme. Consider:
4848
49- inline int foo() {
50- #ifdef __i386__
51- return 1;
49+ int32_t
50+ OSHostByteOrder(void) {
51+ #if defined(__LITTLE_ENDIAN__)
52+ return OSLittleEndian;
53+ #elif defined(__BIG_ENDIAN__)
54+ return OSBigEndian;
5255#else
53- return 2 ;
56+ return OSUnknownByteOrder ;
5457#endif
5558}
5659
57- It would be trivial to mark 'foo ' as being non-portable (tainted) instead of
58- marking the entire translation unit. Then, if foo is never called/used by the
59- current translation unit, the t-u wouldn't be marked non-portable. However,
60- there is no good way to handle stuff like:
60+ It would be trivial to mark 'OSHostByteOrder ' as being non-portable (tainted)
61+ instead of marking the entire translation unit. Then, if OSHostByteOrder is
62+ never called/used by the current translation unit, the t-u wouldn't be marked
63+ non-portable. However, there is no good way to handle stuff like:
6164
6265extern int X, Y;
6366
@@ -70,18 +73,62 @@ int bar() { return X; }
7073When compiling for powerpc, the #define is skipped, so it doesn't know that bar
7174uses a #define that is set on some other target. In practice, limited cases
7275could be handled by scanning the skipped region of a #if, but the fully general
73- case cannot be implemented efficiently.
76+ case cannot be implemented efficiently. In particular, code like this (from
77+ OSByteOrder.h):
7478
75- We probably have to do something like this in the future. The C++ header
79+ #if (defined(__ppc__) || defined(__ppc64__))
80+ #include <libkern/ppc/OSByteOrder.h>
81+ #elif (defined(__i386__) || defined(__x86_64__))
82+ #include <libkern/i386/OSByteOrder.h>
83+ #else
84+ #include <libkern/machine/OSByteOrder.h>
85+ #endif
86+
87+ ... should be fixed by having an initial #ifdef __llvm__ that defines its
88+ contents in terms of the llvm bswap intrinsics. Other things should be handled
89+ on a case-by-case basis.
90+
91+
92+ We probably have to do something smarter like this in the future. The C++ header
7693<limits> contains a lot of code like this:
94+
7795 static const int digits10 = __LDBL_DIG__;
7896 static const int min_exponent = __LDBL_MIN_EXP__;
7997 static const int min_exponent10 = __LDBL_MIN_10_EXP__;
8098 static const float_denorm_style has_denorm
8199 = bool(__LDBL_DENORM_MIN__) ? denorm_present : denorm_absent;
100+
82101 ... since this isn't being used in an #ifdef, it should be easy enough to taint
83102the decl for these ivars.
84103
85104
105+ /usr/include/sys/cdefs.h contains stuff like this:
106+
107+ #if defined(__ppc__)
108+ # if defined(__LDBL_MANT_DIG__) && defined(__DBL_MANT_DIG__) && \
109+ __LDBL_MANT_DIG__ > __DBL_MANT_DIG__
110+ # if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 < 1040
111+ # define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBLStub")
112+ # else
113+ # define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBL128")
114+ # endif
115+ # define __DARWIN_LDBL_COMPAT2(x) __asm("_" __STRING(x) "$LDBL128")
116+ # define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0
117+ # else
118+ # define __DARWIN_LDBL_COMPAT(x) /* nothing */
119+ # define __DARWIN_LDBL_COMPAT2(x) /* nothing */
120+ # define __DARWIN_LONG_DOUBLE_IS_DOUBLE 1
121+ # endif
122+ #elif defined(__i386__) || defined(__ppc64__) || defined(__x86_64__)
123+ # define __DARWIN_LDBL_COMPAT(x) /* nothing */
124+ # define __DARWIN_LDBL_COMPAT2(x) /* nothing */
125+ # define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0
126+ #else
127+ # error Unknown architecture
128+ #endif
129+
130+ An ideal way to solve this issue is to mark __DARWIN_LDBL_COMPAT /
131+ __DARWIN_LDBL_COMPAT2 / __DARWIN_LONG_DOUBLE_IS_DOUBLE as being non-portable
132+ because they depend on non-portable macros.
86133
87134//===---------------------------------------------------------------------===//
0 commit comments