Skip to content

Commit 6fa9792

Browse files
committedMar 9, 2017
[compiler-rt][builtins] Add __isOSVersionAtLeast()
This predicate compares the host's marketing OS version to one passed as argument. Currently, only darwin targets are supported. This is done by parsing the SystemVersion.plist file. Also added in this patch is some lit testing infrastructure for builtins, which previously had none. This part of the patch was written by Alex Lorenz (with some minor modifications). This patch is part of a feature I proposed here: http://lists.llvm.org/pipermail/cfe-dev/2016-July/049851.html Differential revision: https://reviews.llvm.org/D30136 llvm-svn: 297382
1 parent e86b7e2 commit 6fa9792

File tree

9 files changed

+191
-2
lines changed

9 files changed

+191
-2
lines changed
 

‎compiler-rt/lib/builtins/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ set(GENERIC_SOURCES
132132
negvdi2.c
133133
negvsi2.c
134134
negvti2.c
135+
os_version_check.c
135136
paritydi2.c
136137
paritysi2.c
137138
parityti2.c
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* ===-- os_version_check.c - OS version checking -------------------------===
2+
*
3+
* The LLVM Compiler Infrastructure
4+
*
5+
* This file is dual licensed under the MIT and the University of Illinois Open
6+
* Source Licenses. See LICENSE.TXT for details.
7+
*
8+
* ===----------------------------------------------------------------------===
9+
*
10+
* This file implements the function __isOSVersionAtLeast, used by
11+
* Objective-C's @available
12+
*
13+
* ===----------------------------------------------------------------------===
14+
*/
15+
16+
#ifdef __APPLE__
17+
18+
#include <CoreFoundation/CoreFoundation.h>
19+
#include <Dispatch/Dispatch.h>
20+
#include <TargetConditionals.h>
21+
#include <stdint.h>
22+
#include <stdio.h>
23+
#include <stdlib.h>
24+
#include <string.h>
25+
26+
/* These three variables hold the host's OS version. */
27+
static int32_t GlobalMajor, GlobalMinor, GlobalSubminor;
28+
static dispatch_once_t DispatchOnceCounter;
29+
30+
/* Find and parse the SystemVersion.plist file. */
31+
static void parseSystemVersionPList(void *Unused) {
32+
(void)Unused;
33+
34+
char *PListPath = "/System/Library/CoreServices/SystemVersion.plist";
35+
36+
#if TARGET_OS_SIMULATOR
37+
char *PListPathPrefix = getenv("IPHONE_SIMULATOR_ROOT");
38+
if (!PListPathPrefix)
39+
return;
40+
char FullPath[strlen(PListPathPrefix) + strlen(PListPath) + 1];
41+
strcpy(FullPath, PListPathPrefix);
42+
strcat(FullPath, PListPath);
43+
PListPath = FullPath;
44+
#endif
45+
FILE *PropertyList = fopen(PListPath, "r");
46+
if (!PropertyList)
47+
return;
48+
49+
/* Dynamically allocated stuff. */
50+
CFDictionaryRef PListRef = NULL;
51+
CFDataRef FileContentsRef = NULL;
52+
UInt8 *PListBuf = NULL;
53+
54+
fseek(PropertyList, 0, SEEK_END);
55+
long PListFileSize = ftell(PropertyList);
56+
if (PListFileSize < 0)
57+
goto Fail;
58+
rewind(PropertyList);
59+
60+
PListBuf = malloc((size_t)PListFileSize);
61+
if (!PListBuf)
62+
goto Fail;
63+
64+
size_t NumRead = fread(PListBuf, 1, (size_t)PListFileSize, PropertyList);
65+
if (NumRead != (size_t)PListFileSize)
66+
goto Fail;
67+
68+
/* Get the file buffer into CF's format. We pass in a null allocator here *
69+
* because we free PListBuf ourselves */
70+
FileContentsRef = CFDataCreateWithBytesNoCopy(
71+
NULL, PListBuf, (CFIndex)NumRead, kCFAllocatorNull);
72+
if (!FileContentsRef)
73+
goto Fail;
74+
75+
if (&CFPropertyListCreateWithData)
76+
PListRef = CFPropertyListCreateWithData(
77+
NULL, FileContentsRef, kCFPropertyListImmutable, NULL, NULL);
78+
else
79+
PListRef = CFPropertyListCreateFromXMLData(NULL, FileContentsRef,
80+
kCFPropertyListImmutable, NULL);
81+
if (!PListRef)
82+
goto Fail;
83+
84+
CFTypeRef OpaqueValue =
85+
CFDictionaryGetValue(PListRef, CFSTR("ProductVersion"));
86+
if (!OpaqueValue || CFGetTypeID(OpaqueValue) != CFStringGetTypeID())
87+
goto Fail;
88+
89+
char VersionStr[32];
90+
if (!CFStringGetCString((CFStringRef)OpaqueValue, VersionStr,
91+
sizeof(VersionStr), kCFStringEncodingUTF8))
92+
goto Fail;
93+
sscanf(VersionStr, "%d.%d.%d", &GlobalMajor, &GlobalMinor, &GlobalSubminor);
94+
95+
Fail:
96+
if (PListRef)
97+
CFRelease(PListRef);
98+
if (FileContentsRef)
99+
CFRelease(FileContentsRef);
100+
free(PListBuf);
101+
fclose(PropertyList);
102+
}
103+
104+
int32_t __isOSVersionAtLeast(int32_t Major, int32_t Minor, int32_t Subminor) {
105+
/* Populate the global version variables, if they haven't already. */
106+
dispatch_once_f(&DispatchOnceCounter, NULL, parseSystemVersionPList);
107+
108+
if (Major < GlobalMajor) return 1;
109+
if (Major > GlobalMajor) return 0;
110+
if (Minor < GlobalMinor) return 1;
111+
if (Minor > GlobalMinor) return 0;
112+
return Subminor <= GlobalSubminor;
113+
}
114+
115+
#endif

‎compiler-rt/test/CMakeLists.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ configure_lit_site_cfg(
55
${CMAKE_CURRENT_SOURCE_DIR}/lit.common.configured.in
66
${CMAKE_CURRENT_BINARY_DIR}/lit.common.configured)
77

8-
# BlocksRuntime and builtins testsuites are not yet ported to lit.
8+
# BlocksRuntime (and most of builtins) testsuites are not yet ported to lit.
99
# add_subdirectory(BlocksRuntime)
10-
# add_subdirectory(builtins)
1110

1211
set(SANITIZER_COMMON_LIT_TEST_DEPS)
1312
if(COMPILER_RT_STANDALONE_BUILD)
@@ -39,6 +38,9 @@ endif()
3938
# Run sanitizer tests only if we're sure that clang would produce
4039
# working binaries.
4140
if(COMPILER_RT_CAN_EXECUTE_TESTS)
41+
if(COMPILER_RT_BUILD_BUILTINS)
42+
add_subdirectory(builtins)
43+
endif()
4244
if(COMPILER_RT_HAS_ASAN)
4345
add_subdirectory(asan)
4446
endif()
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(BUILTINS_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
2+
3+
set(BUILTINS_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} builtins)
4+
set(BUILTINS_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/TestCases)
5+
6+
# Test cases.
7+
configure_lit_site_cfg(
8+
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
9+
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
10+
)
11+
12+
add_lit_testsuite(check-builtins "Running the Builtins tests"
13+
${BUILTINS_TESTSUITES}
14+
DEPENDS ${BUILTINS_TEST_DEPS})
15+
set_target_properties(check-builtins PROPERTIES FOLDER "Compiler-RT Misc")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def getRoot(config):
2+
if not config.parent:
3+
return config
4+
return getRoot(config.parent)
5+
6+
root = getRoot(config)
7+
8+
if root.host_os not in ['Darwin']:
9+
config.unsupported = True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang %s -o %t -mmacosx-version-min=10.5 -framework CoreFoundation -DMAJOR=%macos_version_major -DMINOR=%macos_version_minor -DSUBMINOR=%macos_version_subminor
2+
// RUN: %run %t
3+
4+
int __isOSVersionAtLeast(int Major, int Minor, int Subminor);
5+
6+
int main() {
7+
if (!__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR))
8+
return 1;
9+
if (__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR + 1))
10+
return 1;
11+
if (SUBMINOR && __isOSVersionAtLeast(MAJOR + 1, MINOR, SUBMINOR - 1))
12+
return 1;
13+
if (SUBMINOR && !__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR - 1))
14+
return 1;
15+
if (MAJOR && !__isOSVersionAtLeast(MAJOR - 1, MINOR + 1, SUBMINOR))
16+
return 1;
17+
18+
return 0;
19+
}

‎compiler-rt/test/builtins/lit.cfg

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- Python -*-
2+
3+
import os
4+
5+
# Setup config name.
6+
config.name = 'Builtins'
7+
8+
# Setup source root.
9+
config.test_source_root = os.path.dirname(__file__)
10+
11+
# Test suffixes.
12+
config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm']
13+
14+
# Define %clang and %clangxx substitutions to use in test RUN lines.
15+
config.substitutions.append( ("%clang ", " " + config.clang + " ") )
16+
17+
if config.host_os == 'Darwin':
18+
config.substitutions.append( ("%macos_version_major", str(config.darwin_osx_version[0])) )
19+
config.substitutions.append( ("%macos_version_minor", str(config.darwin_osx_version[1])) )
20+
config.substitutions.append( ("%macos_version_subminor", str(config.darwin_osx_version[2])) )
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@LIT_SITE_CFG_IN_HEADER@
2+
3+
# Load common config for all compiler-rt lit tests.
4+
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
5+
6+
# Load tool-specific config that would do the real work.
7+
lit_config.load_config(config, "@BUILTINS_LIT_SOURCE_DIR@/lit.cfg")

‎compiler-rt/test/lit.common.cfg

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ if config.host_os == 'Darwin':
129129
try:
130130
osx_version = subprocess.check_output(["sw_vers", "-productVersion"])
131131
osx_version = tuple(int(x) for x in osx_version.split('.'))
132+
config.darwin_osx_version = osx_version
132133
if osx_version >= (10, 11):
133134
config.available_features.add('osx-autointerception')
134135
config.available_features.add('osx-ld64-live_support')

0 commit comments

Comments
 (0)
Please sign in to comment.