From 72616f6db8e2ba7c0f743abba2df111e2e3a5da6 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Fri, 4 Dec 2015 13:23:04 -0500 Subject: [PATCH 01/16] android: start adding a stub target in the build script; doesn't work at all yet --- lib/Basic/Platform.cpp | 4 ++++ utils/build-script-impl | 49 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index ebbc0497b4f28..cc50c5ab52fc8 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -58,6 +58,10 @@ StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) { return "watchos"; } + if (triple.isAndroid()) { + return "android"; + } + if (triple.isMacOSX()) return "macosx"; diff --git a/utils/build-script-impl b/utils/build-script-impl index a11b57e16f5f1..4ebd2449b44c5 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -174,6 +174,9 @@ KNOWN_SETTINGS=( extra-swift-args "" "Extra arguments to pass to swift modules which match regex. Assumed to be a flattened cmake list consisting of [module_regexp, args, module_regexp, args, ...]" sil-verify-all "0" "If enabled, run the sil verifier be run after every SIL pass" swift-enable-ast-verifier "1" "If enabled, and the assertions are enabled, the built Swift compiler will run the AST verifier every time it is invoked" + swift-enable-target-linux "1" "Enable compiler support for targeting Linux" + swift-enable-target-freebsd "1" "Enable compiler support for targeting FreeBSD" + swift-enable-target-android "1" "Enable compiler support for targeting Android" swift-runtime-enable-dtrace "0" "Enable runtime dtrace support" swift-runtime-enable-leak-checker "0" "Enable leaks checking routines in the runtime" use-gold-linker "" "Enable using the gold linker" @@ -393,6 +396,39 @@ function set_deployment_target_based_options() { ) fi + ;; + android-*) + case ${deployment_target} in + android-armv7) + llvm_host_triple="arm-linux-androideabi" + llvm_target_arch="ARM" + cmark_cmake_options=( + -DCMAKE_C_FLAGS="$(cmark_c_flags $deployment_target)" + -DCMAKE_CXX_FLAGS="$(cmark_c_flags $deployment_target)" + -DCMAKE_SYSROOT:PATH="FIXME THE SYSROOT" + ) + swift_cmake_options=( + -DSWIFT_HOST_VARIANT_ARCH="armv7" + ) + ;; + *) + echo "Unknown deployment target" + exit 1 + ;; + esac + native_llvm_build=$(build_directory linux-x86_64 llvm) + llvm_cmake_options=( + -DCMAKE_OSX_SYSROOT:PATH="FIXME THE SYSROOT" + -DLLVM_HOST_TRIPLE:STRING="${llvm_host_triple}" + ) + + if [[ "${llvm_target_arch}" ]] ; then + llvm_cmake_options=( + "${llvm_cmake_options[@]}" + -DLLVM_TARGET_ARCH="${llvm_target_arch}" + ) + fi + ;; *) echo "Unknown compiler deployment target: ${deployment_target}" @@ -776,7 +812,8 @@ for t in ${CROSS_COMPILE_TOOLS_DEPLOYMENT_TARGETS} ; do iphonesimulator-i386 | iphonesimulator-x86_64 | \ iphoneos-arm64 | iphoneos-armv7 | \ appletvos-arm64 | appletvsimulator-x86_64 | \ - watchos-armv7k | watchsimulator-i386) + watchos-armv7k | watchsimulator-i386 | \ + android-armv7 ) CROSS_TOOLS_DEPLOYMENT_TARGETS=( "${CROSS_TOOLS_DEPLOYMENT_TARGETS[@]}" "${t}" @@ -805,6 +842,7 @@ case "$(uname -s -m)" in Linux\ x86_64) STDLIB_DEPLOYMENT_TARGETS=( "linux-x86_64" + "android-armv7" ) ;; Linux\ armv7*) @@ -976,6 +1014,10 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do build_for_this_target=$(not ${SKIP_BUILD_WATCHOS_SIMULATOR}) test_this_target=$(not ${SKIP_TEST_WATCHOS_SIMULATOR}) ;; + android-*) + build_for_this_target=1 + test_this_target=1 + ;; *) echo "Unknown compiler deployment target: ${deployment_target}" exit 1 @@ -1200,6 +1242,9 @@ function common_cross_c_flags() { watchos-armv7k) echo "-arch armv7k -mwatchos-version-min=${DARWIN_DEPLOYMENT_VERSION_WATCHOS}" ;; + android-armv7) + echo "-arch armv7" + ;; esac } @@ -1860,7 +1905,7 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do linux-* | freebsd-* | macosx-*) # OK, we can run tests directly. ;; - iphoneos-* | iphonesimulator-* | appletvos-* | appletvsimulator-* | watchos-* | watchsimulator-*) + iphoneos-* | iphonesimulator-* | appletvos-* | appletvsimulator-* | watchos-* | watchsimulator-* | android-* ) # FIXME: remove this # echo "Don't know how to run tests for ${deployment_target}" continue From 0eb0d8cf8eed54daa5342e0ecc7086ef6ad5c215 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Fri, 4 Dec 2015 14:05:36 -0500 Subject: [PATCH 02/16] android: added target in CMakeLists - won't work since libicu is not available on Android --- CMakeLists.txt | 17 +++++++++++++++-- test/CMakeLists.txt | 3 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4435e1d2c6a53..df43a0abad36c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,9 +391,22 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") # FIXME: This will not work while trying to cross-compile. if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") - configure_sdk_unix(LINUX "Linux" "linux" "linux" "x86_64" "x86_64-unknown-linux-gnu") set(SWIFT_HOST_VARIANT_ARCH "x86_64") - set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64") + set(swift_can_crosscompile_stdlib TRUE) + + is_sdk_requested(LINUX swift_build_linux) + if(swift_build_linux) + configure_sdk_unix(LINUX "Linux" "linux" "linux" "x86_64" "x86_64-unknown-linux-gnu") + set(SWIFT_PRIMARY_VARIANT_SDK_default "LINUX") + set(SWIFT_PRIMARY_VARIANT_ARCH_default "x86_64") + endif() + + is_sdk_requested(ANDROID swift_build_android) + if(swift_build_android AND ${swift_can_crosscompile_stdlib}) + configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi") + set(SWIFT_PRIMARY_VARIANT_SDK_default "ANDROID") + set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv7") + endif() # FIXME: This only matches ARMv7l (by far the most common variant). elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l") configure_sdk_unix(LINUX "Linux" "linux" "linux" "armv7" "armv7-unknown-linux-gnueabihf") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 275a4d571be33..b213da38d3b93 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -57,7 +57,8 @@ function(get_test_dependencies SDK result_var_name) ("${SDK}" STREQUAL "TVOS_SIMULATOR") OR ("${SDK}" STREQUAL "WATCHOS_SIMULATOR") OR ("${SDK}" STREQUAL "LINUX") OR - ("${SDK}" STREQUAL "FREEBSD")) + ("${SDK}" STREQUAL "FREEBSD") OR + ("${SDK}" STREQUAL "ANDROID")) # No extra dependencies. else() message(FATAL_ERROR "Unknown SDK: ${SDK}") From 822581fb754f9c4a9b4efaa66cfb69b192ab7868 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Sat, 5 Dec 2015 20:38:08 -0500 Subject: [PATCH 03/16] android: hardcode ICU path, add NDK to sysroot, started copying link/compile job pools from LLVM's cmake list, force -j1 and split dwarfs when compiling --- CMakeLists.txt | 23 +++++++++++++++++++++++ cmake/modules/AddSwift.cmake | 14 +++++++++++++- cmake/modules/FindICU.cmake | 5 +++++ utils/build-script-impl | 10 ++++++---- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df43a0abad36c..171a870e1e724 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,28 @@ set(SWIFT_NATIVE_CLANG_TOOLS_PATH "" CACHE STRING set(SWIFT_NATIVE_SWIFT_TOOLS_PATH "" CACHE STRING "Path to the directory that contains Swift tools that are executable on the build machine") +# The following only works with the Ninja generator in CMake >= 3.0. +set(SWIFT_PARALLEL_COMPILE_JOBS "" CACHE STRING + "Define the maximum number of concurrent compilation jobs.") +if(SWIFT_PARALLEL_COMPILE_JOBS) + if(CMAKE_VERSION VERSION_LESS 3.0 OR NOT CMAKE_MAKE_PROGRAM MATCHES "ninja") + message(WARNING "Job pooling is only available with Ninja generators and CMake 3.0 and later.") + else() + set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${SWIFT_PARALLEL_COMPILE_JOBS}) + set(CMAKE_JOB_POOL_COMPILE compile_job_pool) + endif() +endif() + +set(SWIFT_PARALLEL_LINK_JOBS "1" CACHE STRING + "Define the maximum number of concurrent link jobs.") +if(SWIFT_PARALLEL_LINK_JOBS) + if(CMAKE_VERSION VERSION_LESS 3.0 OR NOT CMAKE_MAKE_PROGRAM MATCHES "ninja") + message(WARNING "Job pooling is only available with Ninja generators and CMake 3.0 and later.") + else() + set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${SWIFT_PARALLEL_LINK_JOBS}) + set(CMAKE_JOB_POOL_LINK link_job_pool) + endif() +endif() # # User-configurable Darwin-specific options. # @@ -404,6 +426,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") is_sdk_requested(ANDROID swift_build_android) if(swift_build_android AND ${swift_can_crosscompile_stdlib}) configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi") + set(SWIFT_SDK_ANDROID_PATH "/home/zhuowei/ndk/platforms/android-16/arch-arm") set(SWIFT_PRIMARY_VARIANT_SDK_default "ANDROID") set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv7") endif() diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 5cbc985df88ac..f0dbfe8ecbbaf 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -57,6 +57,12 @@ function(_add_variant_c_compile_link_flags list(APPEND result "-isysroot" "${SWIFT_SDK_${sdk}_PATH}") + if("${sdk}" STREQUAL "ANDROID") + list(APPEND result + "--sysroot=${SWIFT_SDK_${sdk}_PATH}") + endif() + + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") list(APPEND result "-arch" "${arch}" @@ -103,6 +109,12 @@ function(_add_variant_c_compile_flags list(APPEND result "-DNDEBUG") endif() + if("${sdk}" STREQUAL "ANDROID") + list(APPEND result + "-I/home/zhuowei/ndk/sources/cxx-stl/llvm-libc++/libcxx/include" + "-I/home/zhuowei/ndk/sources/android/support/include") + endif() + set("${result_var_name}" "${result}" PARENT_SCOPE) endfunction() @@ -1062,7 +1074,7 @@ function(_add_swift_library_single target name) # isn't the standard library. The standard library uses a # linker script that isn't supported by the gold linker. if(NOT SWIFTLIB_SINGLE_IS_STDLIB) - list(APPEND link_flags "-fuse-ld=gold") + list(APPEND link_flags "-fuse-ld=gold -Wl,--gdb-index") endif() endif() endif() diff --git a/cmake/modules/FindICU.cmake b/cmake/modules/FindICU.cmake index a1f631c5f1f47..49b31aab27ef5 100644 --- a/cmake/modules/FindICU.cmake +++ b/cmake/modules/FindICU.cmake @@ -1,5 +1,7 @@ # Find libicu's libraries +# Android FIXME: ICU + include(FindPackageHandleStandardArgs) find_package(PkgConfig) @@ -24,6 +26,9 @@ foreach(MODULE ${ICU_FIND_COMPONENTS}) set(ICU_${MODULE}_LIBRARIES ${ICU_${MODULE}_LIBRARY}) endif() endforeach() +message("FIXME Android: ICU") +set(ICU_I18N_INCLUDE_DIR "/home/zhuowei/icu/source/i18n") +set(ICU_UC_INCLUDE_DIR "/home/zhuowei/icu/source/common") find_package_handle_standard_args(ICU DEFAULT_MSG ${ICU_REQUIRED}) mark_as_advanced(${ICU_REQUIRED}) diff --git a/utils/build-script-impl b/utils/build-script-impl index 4ebd2449b44c5..d37fae4a55a20 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -179,7 +179,7 @@ KNOWN_SETTINGS=( swift-enable-target-android "1" "Enable compiler support for targeting Android" swift-runtime-enable-dtrace "0" "Enable runtime dtrace support" swift-runtime-enable-leak-checker "0" "Enable leaks checking routines in the runtime" - use-gold-linker "" "Enable using the gold linker" + use-gold-linker "1" "Enable using the gold linker" darwin-toolchain-bundle-identifier "" "CFBundleIdentifier for xctoolchain info plist" darwin-toolchain-display-name "" "Display Name for xctoolcain info plist" darwin-toolchain-name "" "Directory name for xctoolchain" @@ -1061,7 +1061,8 @@ COMMON_CMAKE_OPTIONS=( -G "${CMAKE_GENERATOR}" ) -COMMON_C_FLAGS="" +COMMON_C_FLAGS="-gsplit-dwarf" +COMMON_CXX_FLAGS="-gsplit-dwarf" if [[ "${ENABLE_ASAN}" ]] ; then COMMON_CMAKE_OPTIONS=( @@ -1099,6 +1100,7 @@ fi if [[ "${DISTCC}" ]] ; then BUILD_ARGS="${BUILD_ARGS} -j $(distcc -j)" fi +BUILD_ARGS="${BUILD_ARGS} -j1" case "${CMAKE_GENERATOR}" in Ninja) @@ -1480,8 +1482,8 @@ for deployment_target in "${NATIVE_TOOLS_DEPLOYMENT_TARGETS[@]}" "${CROSS_TOOLS_ # gold linker support. cmake_options=( "${cmake_options[@]}" - -DCMAKE_EXE_LINKER_FLAGS:STRING="-fuse-ld=gold" - -DCMAKE_SHARED_LINKER_FLAGS:STRING="-fuse-ld=gold" + -DCMAKE_EXE_LINKER_FLAGS:STRING="-fuse-ld=gold -Wl,--gdb-index" + -DCMAKE_SHARED_LINKER_FLAGS:STRING="-fuse-ld=gold -Wl,--gdb-index" ) fi else From cc95189376dab3de97848b9db598bf2fd9f8bf83 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Sun, 6 Dec 2015 00:17:44 -0500 Subject: [PATCH 04/16] android: stub out some missing methods on Android, disable split dwarf by default --- stdlib/public/runtime/CMakeLists.txt | 1 + stdlib/public/runtime/ProtocolConformance.cpp | 7 +++ stdlib/public/stubs/LibcShims.cpp | 16 +++++- stdlib/public/stubs/Stubs.cpp | 23 ++++++++- stdlib/public/stubs/getline.inc | 49 +++++++++++++++++++ utils/build-script-impl | 8 +-- 6 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 stdlib/public/stubs/getline.inc diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 238e879bfca10..80e1ce44c493e 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -66,5 +66,6 @@ foreach(sdk ${SWIFT_CONFIGURED_SDKS}) endforeach() endif() + # FIXME: Android: make a swift.ld for armv7 android endforeach() diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 4f5315fdea00f..2b829a108f23e 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -307,6 +307,10 @@ static void _addImageProtocolConformances(const mach_header *mh, _addImageProtocolConformancesBlock(conformances, conformancesSize); } #elif defined(__ELF__) +#ifdef __ANDROID__ +#define RTLD_NOLOAD 0 +#endif + static int _addImageProtocolConformances(struct dl_phdr_info *info, size_t size, void * /*data*/) { void *handle; @@ -345,7 +349,10 @@ static void _initializeCallbacksToInspectDylib() { // loaded ones. // FIXME: Find a way to have this continue to happen after. // rdar://problem/19045112 + #ifndef __ANDROID__ + // FIXME: Android: doesn't have dl_iterate_phdr before API 21 dl_iterate_phdr(_addImageProtocolConformances, nullptr); + #endif #else # error No known mechanism to inspect dynamic libraries on this platform. #endif diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp index ea83c3ec7b98d..9f0c63479b7d3 100644 --- a/stdlib/public/stubs/LibcShims.cpp +++ b/stdlib/public/stubs/LibcShims.cpp @@ -17,12 +17,15 @@ #include #include "../SwiftShims/LibcShims.h" -#if defined(__linux__) +#if defined(__linux__) && !defined(__ANDROID__) #include #endif +// android's ssize_t is an int, which is the same size as long int +#ifndef __ANDROID__ static_assert(std::is_same::value, "__swift_ssize_t is wrong"); +#endif namespace swift { @@ -50,7 +53,7 @@ int _swift_stdlib_close(int fd) { return close(fd); } #if defined(__APPLE__) #include size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_size(ptr); } -#elif defined(__GNU_LIBRARY__) +#elif defined(__GNU_LIBRARY__) || defined(__ANDROID__) #include size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_usable_size(const_cast(ptr)); @@ -64,12 +67,21 @@ size_t _swift_stdlib_malloc_size(const void *ptr) { #error No malloc_size analog known for this platform/libc. #endif +#ifndef __ANDROID__ __swift_uint32_t _swift_stdlib_arc4random(void) { return arc4random(); } __swift_uint32_t _swift_stdlib_arc4random_uniform(__swift_uint32_t upper_bound) { return arc4random_uniform(upper_bound); } +#else +// FIXME: Android: chosen by fair dice roll +__swift_uint32_t _swift_stdlib_arc4random(void) { return 4; } +__swift_uint32_t +_swift_stdlib_arc4random_uniform(__swift_uint32_t upper_bound) { + return 0; +} +#endif } // namespace swift diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index a31ed42e14159..076c2ed459643 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -35,6 +35,11 @@ #include "swift/Runtime/Debug.h" #include "swift/Basic/Lazy.h" +#ifdef __ANDROID__ +#include "getline.inc" +#define getline swift_getline +#endif + static uint64_t uint64ToStringImpl(char *Buffer, uint64_t Value, int64_t Radix, bool Uppercase, bool Negative) { @@ -98,7 +103,7 @@ extern "C" uint64_t swift_uint64ToString(char *Buffer, intptr_t BufferLength, /*Negative=*/false); } -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__ANDROID__) static inline locale_t getCLocale() { // On these platforms convenience functions from xlocale.h interpret nullptr // as C locale. @@ -118,6 +123,22 @@ static locale_t getCLocale() { } #endif +#ifdef __ANDROID__ +#define uselocale(a) (nullptr) +static double swift_strtod_l(const char* a, char** b, locale_t c) { + return strtod(a, b); +} +static float swift_strtof_l(const char* a, char** b, locale_t c) { + return strtof(a, b); +} +static long double swift_strtold_l(const char* a, char** b, locale_t c) { + return strtold(a, b); +} +#define strtod_l swift_strtod_l +#define strtof_l swift_strtof_l +#define strtold_l swift_strtold_l +#endif + #if defined(__APPLE__) #define swift_snprintf_l snprintf_l #else diff --git a/stdlib/public/stubs/getline.inc b/stdlib/public/stubs/getline.inc new file mode 100644 index 0000000000000..a020202986fd7 --- /dev/null +++ b/stdlib/public/stubs/getline.inc @@ -0,0 +1,49 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +static ssize_t swift_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *ptr; + + ptr = fgetln(stream, n); + + if (ptr == NULL) { + return -1; + } + + /* Free the original ptr */ + if (*lineptr != NULL) free(*lineptr); + + /* Add one more space for '\0' */ + size_t len = n[0] + 1; + + /* Update the length */ + n[0] = len; + + /* Allocate a new buffer */ + *lineptr = (char*) malloc(len); + + /* Copy over the string */ + memcpy(*lineptr, ptr, len-1); + + /* Write the NULL character */ + (*lineptr)[len-1] = '\0'; + + /* Return the length of the new buffer */ + return len; +} diff --git a/utils/build-script-impl b/utils/build-script-impl index d37fae4a55a20..883552cdee4c8 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1061,8 +1061,8 @@ COMMON_CMAKE_OPTIONS=( -G "${CMAKE_GENERATOR}" ) -COMMON_C_FLAGS="-gsplit-dwarf" -COMMON_CXX_FLAGS="-gsplit-dwarf" +COMMON_C_FLAGS="" +COMMON_CXX_FLAGS="" if [[ "${ENABLE_ASAN}" ]] ; then COMMON_CMAKE_OPTIONS=( @@ -1482,8 +1482,8 @@ for deployment_target in "${NATIVE_TOOLS_DEPLOYMENT_TARGETS[@]}" "${CROSS_TOOLS_ # gold linker support. cmake_options=( "${cmake_options[@]}" - -DCMAKE_EXE_LINKER_FLAGS:STRING="-fuse-ld=gold -Wl,--gdb-index" - -DCMAKE_SHARED_LINKER_FLAGS:STRING="-fuse-ld=gold -Wl,--gdb-index" + -DCMAKE_EXE_LINKER_FLAGS:STRING="-fuse-ld=gold" + -DCMAKE_SHARED_LINKER_FLAGS:STRING="-fuse-ld=gold" ) fi else From 8978c952e56e710a4109619da237b2c4ad89a6aa Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Mon, 7 Dec 2015 16:05:45 -0500 Subject: [PATCH 05/16] android: add path to libgcc; not working (we probably need real compiler_rt) --- CMakeLists.txt | 2 ++ cmake/modules/AddSwift.cmake | 9 +++++++-- utils/build-script-impl | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 171a870e1e724..ed2182df166f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,8 @@ set(SWIFT_NATIVE_CLANG_TOOLS_PATH "" CACHE STRING set(SWIFT_NATIVE_SWIFT_TOOLS_PATH "" CACHE STRING "Path to the directory that contains Swift tools that are executable on the build machine") +set(SWIFT_ANDROID_NDK_PATH "/home/zhuowei/ndk" CACHE STRING + "Path to the directory that contains the Android NDK tools that are executable on the build machine") # The following only works with the Ninja generator in CMake >= 3.0. set(SWIFT_PARALLEL_COMPILE_JOBS "" CACHE STRING "Define the maximum number of concurrent compilation jobs.") diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index f0dbfe8ecbbaf..a165c3633b621 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -111,8 +111,8 @@ function(_add_variant_c_compile_flags if("${sdk}" STREQUAL "ANDROID") list(APPEND result - "-I/home/zhuowei/ndk/sources/cxx-stl/llvm-libc++/libcxx/include" - "-I/home/zhuowei/ndk/sources/android/support/include") + "-I${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libcxx/include" + "-I${SWIFT_ANDROID_NDK_PATH}/sources/android/support/include") endif() set("${result_var_name}" "${result}" PARENT_SCOPE) @@ -174,6 +174,11 @@ function(_add_variant_link_flags list(APPEND result "-lpthread" "-ldl") elseif("${sdk}" STREQUAL "FREEBSD") list(APPEND result "-lpthread") + elseif("${sdk}" STREQUAL "ANDROID") + list(APPEND result + "-ldl" + "-L${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8/thumb" + "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/thumb/libc++_shared.so") else() list(APPEND result "-lobjc") endif() diff --git a/utils/build-script-impl b/utils/build-script-impl index 883552cdee4c8..fd6f1cbda3fb9 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1100,7 +1100,7 @@ fi if [[ "${DISTCC}" ]] ; then BUILD_ARGS="${BUILD_ARGS} -j $(distcc -j)" fi -BUILD_ARGS="${BUILD_ARGS} -j1" +BUILD_ARGS="${BUILD_ARGS} -j2" case "${CMAKE_GENERATOR}" in Ninja) From be753ae9d13fbbb6f6ad6c71a73e725ec41f7ed4 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Mon, 7 Dec 2015 22:39:10 -0500 Subject: [PATCH 06/16] android: add log2 implementation from Android Support and mulodi4 from compiler_rt, hardcode path to libicu for now --- cmake/modules/AddSwift.cmake | 7 +- stdlib/public/core/CMakeLists.txt | 2 +- stdlib/public/stubs/CMakeLists.txt | 2 + stdlib/public/stubs/LibcShims.cpp | 13 +- stdlib/public/stubs/Stubs.cpp | 12 +- .../stubs/android_support/Android_log2.cpp | 5 + .../stubs/android_support/Android_log2f.cpp | 5 + stdlib/public/stubs/android_support/e_log2.c | 120 +++ stdlib/public/stubs/android_support/e_log2f.c | 82 ++ stdlib/public/stubs/android_support/k_log.h | 100 +++ stdlib/public/stubs/android_support/k_logf.h | 39 + .../stubs/android_support/math_private.h | 764 ++++++++++++++++++ stdlib/public/stubs/mulodi4.inc | 57 ++ 13 files changed, 1201 insertions(+), 7 deletions(-) create mode 100644 stdlib/public/stubs/android_support/Android_log2.cpp create mode 100644 stdlib/public/stubs/android_support/Android_log2f.cpp create mode 100644 stdlib/public/stubs/android_support/e_log2.c create mode 100644 stdlib/public/stubs/android_support/e_log2f.c create mode 100644 stdlib/public/stubs/android_support/k_log.h create mode 100644 stdlib/public/stubs/android_support/k_logf.h create mode 100644 stdlib/public/stubs/android_support/math_private.h create mode 100644 stdlib/public/stubs/mulodi4.inc diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index a165c3633b621..1b303630b0a93 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -171,14 +171,15 @@ function(_add_variant_link_flags result) if("${sdk}" STREQUAL "LINUX") - list(APPEND result "-lpthread" "-ldl") + list(APPEND result "-lpthread" "-ldl" "${BSD_LIBRARIES}") elseif("${sdk}" STREQUAL "FREEBSD") list(APPEND result "-lpthread") elseif("${sdk}" STREQUAL "ANDROID") list(APPEND result "-ldl" - "-L${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8/thumb" - "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/thumb/libc++_shared.so") + "-L${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8" + "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so" + "-L/home/zhuowei/libiconv-libicu-android/armeabi-v7a") else() list(APPEND result "-lobjc") endif() diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 89e8a7ebce8a9..772067b7ad5f2 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -162,7 +162,7 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") find_package(BSD REQUIRED) list(APPEND swift_core_private_link_libraries - ${BSD_LIBRARIES}) + ${ICU_UC_LIBRARY} ${ICU_I18N_LIBRARY}) endif() option(SWIFT_CHECK_ESSENTIAL_STDLIB diff --git a/stdlib/public/stubs/CMakeLists.txt b/stdlib/public/stubs/CMakeLists.txt index 4bc5c74342161..4de51baec354e 100644 --- a/stdlib/public/stubs/CMakeLists.txt +++ b/stdlib/public/stubs/CMakeLists.txt @@ -25,6 +25,8 @@ add_swift_library(swiftStdlibStubs IS_STDLIB IS_STDLIB_CORE LibcShims.cpp Stubs.cpp UnicodeExtendedGraphemeClusters.cpp.gyb + android_support/Android_log2.cpp + android_support/Android_log2f.cpp ${swift_stubs_objc_sources} ${swift_stubs_unicode_normalization_sources} C_COMPILE_FLAGS ${SWIFT_CORE_CXX_FLAGS} diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp index 9f0c63479b7d3..f4e9df966297a 100644 --- a/stdlib/public/stubs/LibcShims.cpp +++ b/stdlib/public/stubs/LibcShims.cpp @@ -27,6 +27,12 @@ static_assert(std::is_same::value, "__swift_ssize_t is wrong"); #endif +#ifdef __ANDROID__ +extern "C" { +extern size_t dlmalloc_usable_size(void*); +} +#endif + namespace swift { void _swift_stdlib_free(void *ptr) { free(ptr); } @@ -53,7 +59,7 @@ int _swift_stdlib_close(int fd) { return close(fd); } #if defined(__APPLE__) #include size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_size(ptr); } -#elif defined(__GNU_LIBRARY__) || defined(__ANDROID__) +#elif defined(__GNU_LIBRARY__) #include size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_usable_size(const_cast(ptr)); @@ -63,6 +69,11 @@ size_t _swift_stdlib_malloc_size(const void *ptr) { size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_usable_size(const_cast(ptr)); } +#elif defined(__ANDROID__) +// on Android before API 21 malloc_usable_size is exported by this name +size_t _swift_stdlib_malloc_size(const void *ptr) { + return dlmalloc_usable_size(const_cast(ptr)); +} #else #error No malloc_size analog known for this platform/libc. #endif diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index 076c2ed459643..a73819b47c630 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -36,8 +36,11 @@ #include "swift/Basic/Lazy.h" #ifdef __ANDROID__ +extern "C" { #include "getline.inc" #define getline swift_getline +#include "mulodi4.inc" +} #endif static uint64_t uint64ToStringImpl(char *Buffer, uint64_t Value, @@ -132,11 +135,15 @@ static float swift_strtof_l(const char* a, char** b, locale_t c) { return strtof(a, b); } static long double swift_strtold_l(const char* a, char** b, locale_t c) { - return strtold(a, b); + return strtod(a, b); +} +static long double swift_fmodl(long double a, long double b) { + return fmod(a, b); } #define strtod_l swift_strtod_l #define strtof_l swift_strtof_l #define strtold_l swift_strtold_l +#define fmodl swift_fmodl #endif #if defined(__APPLE__) @@ -242,6 +249,7 @@ extern "C" long double _swift_fmodl(long double lhs, long double rhs) { // on compiler-rt on Linux. // FIXME: rdar://14883575 Libcompiler_rt omits muloti4 #if (defined(__APPLE__) && defined(__arm64__)) || \ + (defined(__ANDROID__) && defined(__arm64__)) || \ (defined(__linux__) && defined(__x86_64__)) || \ (defined(__linux__) && defined(__aarch64__)) @@ -288,7 +296,7 @@ __muloti4(ti_int a, ti_int b, int* overflow) #endif -#if defined(__linux__) && defined(__arm__) +#if defined(__linux__) && defined(__arm__) && !defined(__ANDROID__) // Similar to above, but with mulodi4. Perhaps this is // something that shouldn't be done, and is a bandaid over // some other lower-level architecture issue that I'm diff --git a/stdlib/public/stubs/android_support/Android_log2.cpp b/stdlib/public/stubs/android_support/Android_log2.cpp new file mode 100644 index 0000000000000..6c99f14a3db90 --- /dev/null +++ b/stdlib/public/stubs/android_support/Android_log2.cpp @@ -0,0 +1,5 @@ +#ifdef __ANDROID__ +extern "C" { +#include "e_log2.c" +} +#endif diff --git a/stdlib/public/stubs/android_support/Android_log2f.cpp b/stdlib/public/stubs/android_support/Android_log2f.cpp new file mode 100644 index 0000000000000..a8ac93dd2e2f1 --- /dev/null +++ b/stdlib/public/stubs/android_support/Android_log2f.cpp @@ -0,0 +1,5 @@ +#ifdef __ANDROID__ +extern "C" { +#include "e_log2f.c" +} +#endif diff --git a/stdlib/public/stubs/android_support/e_log2.c b/stdlib/public/stubs/android_support/e_log2.c new file mode 100644 index 0000000000000..5d69771b8d4bd --- /dev/null +++ b/stdlib/public/stubs/android_support/e_log2.c @@ -0,0 +1,120 @@ + +/* @(#)e_log10.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Return the base 2 logarithm of x. See e_log.c and k_log.h for most + * comments. + * + * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel, + * then does the combining and scaling steps + * log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k + * in not-quite-routine extra precision. + */ + +#include + +#include "math.h" +#include "math_private.h" +#include "k_log.h" + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */ +ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ + +static const double zero = 0.0; +static volatile double vzero = 0.0; + +double +__ieee754_log2(double x) +{ + double f,hfsq,hi,lo,r,val_hi,val_lo,w,y; + int32_t i,k,hx; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/vzero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + if (hx == 0x3ff00000 && lx == 0) + return zero; /* log(1) = +0 */ + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + y = (double)k; + f = x - 1.0; + hfsq = 0.5*f*f; + r = k_log1p(f); + + /* + * f-hfsq must (for args near 1) be evaluated in extra precision + * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2). + * This is fairly efficient since f-hfsq only depends on f, so can + * be evaluated in parallel with R. Not combining hfsq with R also + * keeps R small (though not as small as a true `lo' term would be), + * so that extra precision is not needed for terms involving R. + * + * Compiler bugs involving extra precision used to break Dekker's + * theorem for spitting f-hfsq as hi+lo, unless double_t was used + * or the multi-precision calculations were avoided when double_t + * has extra precision. These problems are now automatically + * avoided as a side effect of the optimization of combining the + * Dekker splitting step with the clear-low-bits step. + * + * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra + * precision to avoid a very large cancellation when x is very near + * these values. Unlike the above cancellations, this problem is + * specific to base 2. It is strange that adding +-1 is so much + * harder than adding +-ln2 or +-log10_2. + * + * This uses Dekker's theorem to normalize y+val_hi, so the + * compiler bugs are back in some configurations, sigh. And I + * don't want to used double_t to avoid them, since that gives a + * pessimization and the support for avoiding the pessimization + * is not yet available. + * + * The multi-precision calculations for the multiplications are + * routine. + */ + hi = f - hfsq; + SET_LOW_WORD(hi,0); + lo = (f - hi) - hfsq + r; + val_hi = hi*ivln2hi; + val_lo = (lo+hi)*ivln2lo + lo*ivln2hi; + + /* spadd(val_hi, val_lo, y), except for not using double_t: */ + w = y + val_hi; + val_lo += (y - w) + val_hi; + val_hi = w; + + return val_lo + val_hi; +} + +#if (LDBL_MANT_DIG == 53) && !defined(__le32__) && !defined(__le64__) +#define __weak_reference(sym,alias) \ + __asm__(".weak " #alias); \ + __asm__(".equ " #alias ", " #sym) +__weak_reference(log2, log2l); +#endif diff --git a/stdlib/public/stubs/android_support/e_log2f.c b/stdlib/public/stubs/android_support/e_log2f.c new file mode 100644 index 0000000000000..1794484e64ecc --- /dev/null +++ b/stdlib/public/stubs/android_support/e_log2f.c @@ -0,0 +1,82 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Float version of e_log2.c. See the latter for most comments. + */ + +#include "math.h" +#include "math_private.h" +#include "k_logf.h" + +static const float +two25 = 3.3554432000e+07, /* 0x4c000000 */ +ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */ +ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */ + +static const float zero = 0.0; +static volatile float vzero = 0.0; + +float +__ieee754_log2f(float x) +{ + float f,hfsq,hi,lo,r,y; + int32_t i,k,hx; + + GET_FLOAT_WORD(hx,x); + + k=0; + if (hx < 0x00800000) { /* x < 2**-126 */ + if ((hx&0x7fffffff)==0) + return -two25/vzero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 25; x *= two25; /* subnormal number, scale up x */ + GET_FLOAT_WORD(hx,x); + } + if (hx >= 0x7f800000) return x+x; + if (hx == 0x3f800000) + return zero; /* log(1) = +0 */ + k += (hx>>23)-127; + hx &= 0x007fffff; + i = (hx+(0x4afb0d))&0x800000; + SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ + k += (i>>23); + y = (float)k; + f = x - (float)1.0; + hfsq = (float)0.5*f*f; + r = k_log1pf(f); + + /* + * We no longer need to avoid falling into the multi-precision + * calculations due to compiler bugs breaking Dekker's theorem. + * Keep avoiding this as an optimization. See e_log2.c for more + * details (some details are here only because the optimization + * is not yet available in double precision). + * + * Another compiler bug turned up. With gcc on i386, + * (ivln2lo + ivln2hi) would be evaluated in float precision + * despite runtime evaluations using double precision. So we + * must cast one of its terms to float_t. This makes the whole + * expression have type float_t, so return is forced to waste + * time clobbering its extra precision. + */ + if (sizeof(float_t) > sizeof(float)) + return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y; + + hi = f - hfsq; + GET_FLOAT_WORD(hx,hi); + SET_FLOAT_WORD(hi,hx&0xfffff000); + lo = (f - hi) - hfsq + r; + return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y; +} diff --git a/stdlib/public/stubs/android_support/k_log.h b/stdlib/public/stubs/android_support/k_log.h new file mode 100644 index 0000000000000..aaff8bd9000e7 --- /dev/null +++ b/stdlib/public/stubs/android_support/k_log.h @@ -0,0 +1,100 @@ + +/* @(#)e_log.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * k_log1p(f): + * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)]. + * + * The following describes the overall strategy for computing + * logarithms in base e. The argument reduction and adding the final + * term of the polynomial are done by the caller for increased accuracy + * when different bases are used. + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +static const double +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +/* + * We always inline k_log1p(), since doing so produces a + * substantial performance improvement (~40% on amd64). + */ +static inline double +k_log1p(double f) +{ + double hfsq,s,z,R,w,t1,t2; + + s = f/(2.0+f); + z = s*s; + w = z*z; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + R = t2+t1; + hfsq=0.5*f*f; + return s*(hfsq+R); +} diff --git a/stdlib/public/stubs/android_support/k_logf.h b/stdlib/public/stubs/android_support/k_logf.h new file mode 100644 index 0000000000000..71c547e888ae6 --- /dev/null +++ b/stdlib/public/stubs/android_support/k_logf.h @@ -0,0 +1,39 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Float version of k_log.h. See the latter for most comments. + */ + +static const float +/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ +Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ +Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ +Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ +Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ + +static inline float +k_log1pf(float f) +{ + float hfsq,s,z,R,w,t1,t2; + + s = f/((float)2.0+f); + z = s*s; + w = z*z; + t1= w*(Lg2+w*Lg4); + t2= z*(Lg1+w*Lg3); + R = t2+t1; + hfsq=(float)0.5*f*f; + return s*(hfsq+R); +} diff --git a/stdlib/public/stubs/android_support/math_private.h b/stdlib/public/stubs/android_support/math_private.h new file mode 100644 index 0000000000000..8ebc7fbf30c8e --- /dev/null +++ b/stdlib/public/stubs/android_support/math_private.h @@ -0,0 +1,764 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + * $FreeBSD$ + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +#include +#include + +/* + * The original fdlibm code used statements like: + * n0 = ((*(int*)&one)>>29)^1; * index of high word * + * ix0 = *(n0+(int*)&x); * high word of x * + * ix1 = *((1-n0)+(int*)&x); * low word of x * + * to dig two 32 bit words out of the 64 bit IEEE floating point + * value. That is non-ANSI, and, moreover, the gcc instruction + * scheduler gets it wrong. We instead use the following macros. + * Unlike the original code, we determine the endianness at compile + * time, not at run time; I don't see much benefit to selecting + * endianness at run time. + */ + +/* + * A union which permits us to convert between a double and two 32 bit + * ints. + */ + +#ifdef __arm__ +#if defined(__VFP_FP__) +#define IEEE_WORD_ORDER BYTE_ORDER +#else +#define IEEE_WORD_ORDER BIG_ENDIAN +#endif +#else /* __arm__ */ +#define IEEE_WORD_ORDER BYTE_ORDER +#endif + +#if IEEE_WORD_ORDER == BIG_ENDIAN + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; + struct + { + u_int64_t w; + } xparts; +} ieee_double_shape_type; + +#endif + +#if IEEE_WORD_ORDER == LITTLE_ENDIAN + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; + struct + { + u_int64_t w; + } xparts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get a 64-bit int from a double. */ +#define EXTRACT_WORD64(ix,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix) = ew_u.xparts.w; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set a double from a 64-bit int. */ +#define INSERT_WORD64(d,ix) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.xparts.w = (ix); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* + * A union which permits us to convert between a float and a 32 bit + * int. + */ + +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +/* + * Get expsign and mantissa as 16 bit and 64 bit ints from an 80 bit long + * double. + */ + +#define EXTRACT_LDBL80_WORDS(ix0,ix1,d) \ +do { \ + union IEEEl2bits ew_u; \ + ew_u.e = (d); \ + (ix0) = ew_u.xbits.expsign; \ + (ix1) = ew_u.xbits.man; \ +} while (0) + +/* + * Get expsign and mantissa as one 16 bit and two 64 bit ints from a 128 bit + * long double. + */ + +#define EXTRACT_LDBL128_WORDS(ix0,ix1,ix2,d) \ +do { \ + union IEEEl2bits ew_u; \ + ew_u.e = (d); \ + (ix0) = ew_u.xbits.expsign; \ + (ix1) = ew_u.xbits.manh; \ + (ix2) = ew_u.xbits.manl; \ +} while (0) + +/* Get expsign as a 16 bit int from a long double. */ + +#define GET_LDBL_EXPSIGN(i,d) \ +do { \ + union IEEEl2bits ge_u; \ + ge_u.e = (d); \ + (i) = ge_u.xbits.expsign; \ +} while (0) + +/* + * Set an 80 bit long double from a 16 bit int expsign and a 64 bit int + * mantissa. + */ + +#define INSERT_LDBL80_WORDS(d,ix0,ix1) \ +do { \ + union IEEEl2bits iw_u; \ + iw_u.xbits.expsign = (ix0); \ + iw_u.xbits.man = (ix1); \ + (d) = iw_u.e; \ +} while (0) + +/* + * Set a 128 bit long double from a 16 bit int expsign and two 64 bit ints + * comprising the mantissa. + */ + +#define INSERT_LDBL128_WORDS(d,ix0,ix1,ix2) \ +do { \ + union IEEEl2bits iw_u; \ + iw_u.xbits.expsign = (ix0); \ + iw_u.xbits.manh = (ix1); \ + iw_u.xbits.manl = (ix2); \ + (d) = iw_u.e; \ +} while (0) + +/* Set expsign of a long double from a 16 bit int. */ + +#define SET_LDBL_EXPSIGN(d,v) \ +do { \ + union IEEEl2bits se_u; \ + se_u.e = (d); \ + se_u.xbits.expsign = (v); \ + (d) = se_u.e; \ +} while (0) + +#ifdef __i386__ +/* Long double constants are broken on i386. */ +#define LD80C(m, ex, v) { \ + .xbits.man = __CONCAT(m, ULL), \ + .xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0), \ +} +#else +/* The above works on non-i386 too, but we use this to check v. */ +#define LD80C(m, ex, v) { .e = (v), } +#endif + +#ifdef FLT_EVAL_METHOD +/* + * Attempt to get strict C99 semantics for assignment with non-C99 compilers. + */ +#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 +#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) +#else +#define STRICT_ASSIGN(type, lval, rval) do { \ + volatile type __lval; \ + \ + if (sizeof(type) >= sizeof(long double)) \ + (lval) = (rval); \ + else { \ + __lval = (rval); \ + (lval) = __lval; \ + } \ +} while (0) +#endif +#endif /* FLT_EVAL_METHOD */ + +/* Support switching the mode to FP_PE if necessary. */ +#if defined(__i386__) && !defined(NO_FPSETPREC) +#define ENTERI() \ + long double __retval; \ + fp_prec_t __oprec; \ + \ + if ((__oprec = fpgetprec()) != FP_PE) \ + fpsetprec(FP_PE) +#define RETURNI(x) do { \ + __retval = (x); \ + if (__oprec != FP_PE) \ + fpsetprec(__oprec); \ + RETURNF(__retval); \ +} while (0) +#else +#define ENTERI(x) +#define RETURNI(x) RETURNF(x) +#endif + +/* Default return statement if hack*_t() is not used. */ +#define RETURNF(v) return (v) + +/* + * 2sum gives the same result as 2sumF without requiring |a| >= |b| or + * a == 0, but is slower. + */ +#define _2sum(a, b) do { \ + __typeof(a) __s, __w; \ + \ + __w = (a) + (b); \ + __s = __w - (a); \ + (b) = ((a) - (__w - __s)) + ((b) - __s); \ + (a) = __w; \ +} while (0) + +/* + * 2sumF algorithm. + * + * "Normalize" the terms in the infinite-precision expression a + b for + * the sum of 2 floating point values so that b is as small as possible + * relative to 'a'. (The resulting 'a' is the value of the expression in + * the same precision as 'a' and the resulting b is the rounding error.) + * |a| must be >= |b| or 0, b's type must be no larger than 'a's type, and + * exponent overflow or underflow must not occur. This uses a Theorem of + * Dekker (1971). See Knuth (1981) 4.2.2 Theorem C. The name "TwoSum" + * is apparently due to Skewchuk (1997). + * + * For this to always work, assignment of a + b to 'a' must not retain any + * extra precision in a + b. This is required by C standards but broken + * in many compilers. The brokenness cannot be worked around using + * STRICT_ASSIGN() like we do elsewhere, since the efficiency of this + * algorithm would be destroyed by non-null strict assignments. (The + * compilers are correct to be broken -- the efficiency of all floating + * point code calculations would be destroyed similarly if they forced the + * conversions.) + * + * Fortunately, a case that works well can usually be arranged by building + * any extra precision into the type of 'a' -- 'a' should have type float_t, + * double_t or long double. b's type should be no larger than 'a's type. + * Callers should use these types with scopes as large as possible, to + * reduce their own extra-precision and efficiciency problems. In + * particular, they shouldn't convert back and forth just to call here. + */ +#ifdef DEBUG +#define _2sumF(a, b) do { \ + __typeof(a) __w; \ + volatile __typeof(a) __ia, __ib, __r, __vw; \ + \ + __ia = (a); \ + __ib = (b); \ + assert(__ia == 0 || fabsl(__ia) >= fabsl(__ib)); \ + \ + __w = (a) + (b); \ + (b) = ((a) - __w) + (b); \ + (a) = __w; \ + \ + /* The next 2 assertions are weak if (a) is already long double. */ \ + assert((long double)__ia + __ib == (long double)(a) + (b)); \ + __vw = __ia + __ib; \ + __r = __ia - __vw; \ + __r += __ib; \ + assert(__vw == (a) && __r == (b)); \ +} while (0) +#else /* !DEBUG */ +#define _2sumF(a, b) do { \ + __typeof(a) __w; \ + \ + __w = (a) + (b); \ + (b) = ((a) - __w) + (b); \ + (a) = __w; \ +} while (0) +#endif /* DEBUG */ + +/* + * Set x += c, where x is represented in extra precision as a + b. + * x must be sufficiently normalized and sufficiently larger than c, + * and the result is then sufficiently normalized. + * + * The details of ordering are that |a| must be >= |c| (so that (a, c) + * can be normalized without extra work to swap 'a' with c). The details of + * the normalization are that b must be small relative to the normalized 'a'. + * Normalization of (a, c) makes the normalized c tiny relative to the + * normalized a, so b remains small relative to 'a' in the result. However, + * b need not ever be tiny relative to 'a'. For example, b might be about + * 2**20 times smaller than 'a' to give about 20 extra bits of precision. + * That is usually enough, and adding c (which by normalization is about + * 2**53 times smaller than a) cannot change b significantly. However, + * cancellation of 'a' with c in normalization of (a, c) may reduce 'a' + * significantly relative to b. The caller must ensure that significant + * cancellation doesn't occur, either by having c of the same sign as 'a', + * or by having |c| a few percent smaller than |a|. Pre-normalization of + * (a, b) may help. + * + * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2 + * exercise 19). We gain considerable efficiency by requiring the terms to + * be sufficiently normalized and sufficiently increasing. + */ +#define _3sumF(a, b, c) do { \ + __typeof(a) __tmp; \ + \ + __tmp = (c); \ + _2sumF(__tmp, (a)); \ + (b) += (a); \ + (a) = __tmp; \ +} while (0) + +/* + * Common routine to process the arguments to nan(), nanf(), and nanl(). + */ +void _scan_nan(uint32_t *__words, int __num_words, const char *__s); + +#ifdef _COMPLEX_H + +/* + * C99 specifies that complex numbers have the same representation as + * an array of two elements, where the first element is the real part + * and the second element is the imaginary part. + */ +typedef union { + float complex f; + float a[2]; +} float_complex; +typedef union { + double complex f; + double a[2]; +} double_complex; +typedef union { + long double complex f; + long double a[2]; +} long_double_complex; +#define REALPART(z) ((z).a[0]) +#define IMAGPART(z) ((z).a[1]) + +/* + * Inline functions that can be used to construct complex values. + * + * The C99 standard intends x+I*y to be used for this, but x+I*y is + * currently unusable in general since gcc introduces many overflow, + * underflow, sign and efficiency bugs by rewriting I*y as + * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product. + * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted + * to -0.0+I*0.0. + */ +static __inline float complex +cpackf(float x, float y) +{ + float_complex z; + + REALPART(z) = x; + IMAGPART(z) = y; + return (z.f); +} + +static __inline double complex +cpack(double x, double y) +{ + double_complex z; + + REALPART(z) = x; + IMAGPART(z) = y; + return (z.f); +} + +static __inline long double complex +cpackl(long double x, long double y) +{ + long_double_complex z; + + REALPART(z) = x; + IMAGPART(z) = y; + return (z.f); +} +#endif /* _COMPLEX_H */ + +#ifdef __GNUCLIKE_ASM + +/* Asm versions of some functions. */ + +#ifdef __amd64__ +static __inline int +irint(double x) +{ + int n; + + asm("cvtsd2si %1,%0" : "=r" (n) : "x" (x)); + return (n); +} +#define HAVE_EFFICIENT_IRINT +#endif + +#ifdef __i386__ +static __inline int +irint(double x) +{ + int n; + + asm("fistl %0" : "=m" (n) : "t" (x)); + return (n); +} +#define HAVE_EFFICIENT_IRINT +#endif + +#if defined(__amd64__) || defined(__i386__) +static __inline int +irintl(long double x) +{ + int n; + + asm("fistl %0" : "=m" (n) : "t" (x)); + return (n); +} +#define HAVE_EFFICIENT_IRINTL +#endif + +#endif /* __GNUCLIKE_ASM */ + +#ifdef DEBUG +#if defined(__amd64__) || defined(__i386__) +#define breakpoint() asm("int $3") +#else +#include + +#define breakpoint() raise(SIGTRAP) +#endif +#endif + +/* Write a pari script to test things externally. */ +#ifdef DOPRINT +#include + +#ifndef DOPRINT_SWIZZLE +#define DOPRINT_SWIZZLE 0 +#endif + +#ifdef DOPRINT_LD80 + +#define DOPRINT_START(xp) do { \ + uint64_t __lx; \ + uint16_t __hx; \ + \ + /* Hack to give more-problematic args. */ \ + EXTRACT_LDBL80_WORDS(__hx, __lx, *xp); \ + __lx ^= DOPRINT_SWIZZLE; \ + INSERT_LDBL80_WORDS(*xp, __hx, __lx); \ + printf("x = %.21Lg; ", (long double)*xp); \ +} while (0) +#define DOPRINT_END1(v) \ + printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) +#define DOPRINT_END2(hi, lo) \ + printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ + (long double)(hi), (long double)(lo)) + +#elif defined(DOPRINT_D64) + +#define DOPRINT_START(xp) do { \ + uint32_t __hx, __lx; \ + \ + EXTRACT_WORDS(__hx, __lx, *xp); \ + __lx ^= DOPRINT_SWIZZLE; \ + INSERT_WORDS(*xp, __hx, __lx); \ + printf("x = %.21Lg; ", (long double)*xp); \ +} while (0) +#define DOPRINT_END1(v) \ + printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) +#define DOPRINT_END2(hi, lo) \ + printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ + (long double)(hi), (long double)(lo)) + +#elif defined(DOPRINT_F32) + +#define DOPRINT_START(xp) do { \ + uint32_t __hx; \ + \ + GET_FLOAT_WORD(__hx, *xp); \ + __hx ^= DOPRINT_SWIZZLE; \ + SET_FLOAT_WORD(*xp, __hx); \ + printf("x = %.21Lg; ", (long double)*xp); \ +} while (0) +#define DOPRINT_END1(v) \ + printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) +#define DOPRINT_END2(hi, lo) \ + printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ + (long double)(hi), (long double)(lo)) + +#else /* !DOPRINT_LD80 && !DOPRINT_D64 (LD128 only) */ + +#ifndef DOPRINT_SWIZZLE_HIGH +#define DOPRINT_SWIZZLE_HIGH 0 +#endif + +#define DOPRINT_START(xp) do { \ + uint64_t __lx, __llx; \ + uint16_t __hx; \ + \ + EXTRACT_LDBL128_WORDS(__hx, __lx, __llx, *xp); \ + __llx ^= DOPRINT_SWIZZLE; \ + __lx ^= DOPRINT_SWIZZLE_HIGH; \ + INSERT_LDBL128_WORDS(*xp, __hx, __lx, __llx); \ + printf("x = %.36Lg; ", (long double)*xp); \ +} while (0) +#define DOPRINT_END1(v) \ + printf("y = %.36Lg; z = 0; show(x, y, z);\n", (long double)(v)) +#define DOPRINT_END2(hi, lo) \ + printf("y = %.36Lg; z = %.36Lg; show(x, y, z);\n", \ + (long double)(hi), (long double)(lo)) + +#endif /* DOPRINT_LD80 */ + +#else /* !DOPRINT */ +#define DOPRINT_START(xp) +#define DOPRINT_END1(v) +#define DOPRINT_END2(hi, lo) +#endif /* DOPRINT */ + +#define RETURNP(x) do { \ + DOPRINT_END1(x); \ + RETURNF(x); \ +} while (0) +#define RETURNPI(x) do { \ + DOPRINT_END1(x); \ + RETURNI(x); \ +} while (0) +#define RETURN2P(x, y) do { \ + DOPRINT_END2((x), (y)); \ + RETURNF((x) + (y)); \ +} while (0) +#define RETURN2PI(x, y) do { \ + DOPRINT_END2((x), (y)); \ + RETURNI((x) + (y)); \ +} while (0) +#ifdef STRUCT_RETURN +#define RETURNSP(rp) do { \ + if (!(rp)->lo_set) \ + RETURNP((rp)->hi); \ + RETURN2P((rp)->hi, (rp)->lo); \ +} while (0) +#define RETURNSPI(rp) do { \ + if (!(rp)->lo_set) \ + RETURNPI((rp)->hi); \ + RETURN2PI((rp)->hi, (rp)->lo); \ +} while (0) +#endif +#define SUM2P(x, y) ({ \ + const __typeof (x) __x = (x); \ + const __typeof (y) __y = (y); \ + \ + DOPRINT_END2(__x, __y); \ + __x + __y; \ +}) + +/* + * ieee style elementary functions + * + * We rename functions here to improve other sources' diffability + * against fdlibm. + */ +#define __ieee754_sqrt sqrt +#define __ieee754_acos acos +#define __ieee754_acosh acosh +#define __ieee754_log log +#define __ieee754_log2 log2 +#define __ieee754_atanh atanh +#define __ieee754_asin asin +#define __ieee754_atan2 atan2 +#define __ieee754_exp exp +#define __ieee754_cosh cosh +#define __ieee754_fmod fmod +#define __ieee754_pow pow +#define __ieee754_lgamma lgamma +#define __ieee754_gamma gamma +#define __ieee754_lgamma_r lgamma_r +#define __ieee754_gamma_r gamma_r +#define __ieee754_log10 log10 +#define __ieee754_sinh sinh +#define __ieee754_hypot hypot +#define __ieee754_j0 j0 +#define __ieee754_j1 j1 +#define __ieee754_y0 y0 +#define __ieee754_y1 y1 +#define __ieee754_jn jn +#define __ieee754_yn yn +#define __ieee754_remainder remainder +#define __ieee754_scalb scalb +#define __ieee754_sqrtf sqrtf +#define __ieee754_acosf acosf +#define __ieee754_acoshf acoshf +#define __ieee754_logf logf +#define __ieee754_atanhf atanhf +#define __ieee754_asinf asinf +#define __ieee754_atan2f atan2f +#define __ieee754_expf expf +#define __ieee754_coshf coshf +#define __ieee754_fmodf fmodf +#define __ieee754_powf powf +#define __ieee754_lgammaf lgammaf +#define __ieee754_gammaf gammaf +#define __ieee754_lgammaf_r lgammaf_r +#define __ieee754_gammaf_r gammaf_r +#define __ieee754_log10f log10f +#define __ieee754_log2f log2f +#define __ieee754_sinhf sinhf +#define __ieee754_hypotf hypotf +#define __ieee754_j0f j0f +#define __ieee754_j1f j1f +#define __ieee754_y0f y0f +#define __ieee754_y1f y1f +#define __ieee754_jnf jnf +#define __ieee754_ynf ynf +#define __ieee754_remainderf remainderf +#define __ieee754_scalbf scalbf + +/* fdlibm kernel function */ +int __kernel_rem_pio2(double*,double*,int,int,int); + +/* double precision kernel functions */ +#ifndef INLINE_REM_PIO2 +int __ieee754_rem_pio2(double,double*); +#endif +double __kernel_sin(double,double,int); +double __kernel_cos(double,double); +double __kernel_tan(double,double,int); +double __ldexp_exp(double,int); +#ifdef _COMPLEX_H +double complex __ldexp_cexp(double complex,int); +#endif + +/* float precision kernel functions */ +#ifndef INLINE_REM_PIO2F +int __ieee754_rem_pio2f(float,double*); +#endif +#ifndef INLINE_KERNEL_SINDF +float __kernel_sindf(double); +#endif +#ifndef INLINE_KERNEL_COSDF +float __kernel_cosdf(double); +#endif +#ifndef INLINE_KERNEL_TANDF +float __kernel_tandf(double,int); +#endif +float __ldexp_expf(float,int); +#ifdef _COMPLEX_H +float complex __ldexp_cexpf(float complex,int); +#endif + +/* long double precision kernel functions */ +long double __kernel_sinl(long double, long double, int); +long double __kernel_cosl(long double, long double); +long double __kernel_tanl(long double, long double, int); + +#endif /* !_MATH_PRIVATE_H_ */ diff --git a/stdlib/public/stubs/mulodi4.inc b/stdlib/public/stubs/mulodi4.inc new file mode 100644 index 0000000000000..2764e6b3ca868 --- /dev/null +++ b/stdlib/public/stubs/mulodi4.inc @@ -0,0 +1,57 @@ +/*===-- mulodi4.c - Implement __mulodi4 -----------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __mulodi4 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +typedef long long di_int; +/* Returns: a * b */ + +/* Effects: sets *overflow to 1 if a * b overflows */ + +di_int +__mulodi4(di_int a, di_int b, int* overflow) +{ + const int N = (int)(sizeof(di_int) * CHAR_BIT); + const di_int MIN = (di_int)1 << (N-1); + const di_int MAX = ~MIN; + *overflow = 0; + di_int result = a * b; + if (a == MIN) + { + if (b != 0 && b != 1) + *overflow = 1; + return result; + } + if (b == MIN) + { + if (a != 0 && a != 1) + *overflow = 1; + return result; + } + di_int sa = a >> (N - 1); + di_int abs_a = (a ^ sa) - sa; + di_int sb = b >> (N - 1); + di_int abs_b = (b ^ sb) - sb; + if (abs_a < 2 || abs_b < 2) + return result; + if (sa == sb) + { + if (abs_a > MAX / abs_b) + *overflow = 1; + } + else + { + if (abs_a > MIN / -abs_b) + *overflow = 1; + } + return result; +} From bff3b59572b0fb05121980b7e1611160737ba12d Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Tue, 8 Dec 2015 02:11:49 -0500 Subject: [PATCH 07/16] android: start working on bionic wrapper module; pass Bsymbolic to stop linker from complaining --- cmake/modules/AddSwift.cmake | 1 + stdlib/public/Bionic/CMakeLists.txt | 41 +++ stdlib/public/Bionic/Glibc.swift | 76 ++++++ stdlib/public/Bionic/README.md | 5 + stdlib/public/Bionic/module.map | 373 ++++++++++++++++++++++++++++ stdlib/public/CMakeLists.txt | 1 + stdlib/public/Glibc/CMakeLists.txt | 1 + 7 files changed, 498 insertions(+) create mode 100644 stdlib/public/Bionic/CMakeLists.txt create mode 100644 stdlib/public/Bionic/Glibc.swift create mode 100644 stdlib/public/Bionic/README.md create mode 100644 stdlib/public/Bionic/module.map diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 1b303630b0a93..dadfbfe208b8c 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -176,6 +176,7 @@ function(_add_variant_link_flags list(APPEND result "-lpthread") elseif("${sdk}" STREQUAL "ANDROID") list(APPEND result + "-Wl,-Bsymbolic" "-ldl" "-L${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8" "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so" diff --git a/stdlib/public/Bionic/CMakeLists.txt b/stdlib/public/Bionic/CMakeLists.txt new file mode 100644 index 0000000000000..492c4e7e81fc4 --- /dev/null +++ b/stdlib/public/Bionic/CMakeLists.txt @@ -0,0 +1,41 @@ +set(sources + module.map + ) +set(output_dir "${SWIFTLIB_DIR}/bionic") + +set(commands + COMMAND ${CMAKE_COMMAND} "-E" "make_directory" "${output_dir}") +set(outputs) +foreach(input ${sources}) + #list(APPEND commands + # COMMAND + # "${CMAKE_COMMAND}" "-E" "copy_if_different" + # "${CMAKE_CURRENT_SOURCE_DIR}/${input}" + # "${output_dir}/${input}") + list(APPEND commands + COMMAND + "sed" "-e" "s@SYSROOT@/home/zhuowei/ndk/platforms/android-16/arch-arm@g" + "${CMAKE_CURRENT_SOURCE_DIR}/${input}" + ">" + "${output_dir}/${input}") + list(APPEND outputs "${output_dir}/${input}") +endforeach() +# Put the output dir itself last so that it isn't considered the primary output. +list(APPEND outputs "${output_dir}") +add_custom_command_target(unused_var + ${commands} + CUSTOM_TARGET_NAME "copy_bionic_module" + OUTPUT "${outputs}" + DEPENDS "${sources}" + COMMENT "Copying Bionic module to ${output_dir}") + +swift_install_in_component(stdlib + FILES ${sources} + DESTINATION "lib/swift/bionic") + +add_swift_library(swiftGlibc IS_SDK_OVERLAY + Glibc.swift + FILE_DEPENDS copy_bionic_module "${SWIFTLIB_DIR}/bionic" + TARGET_SDKS ANDROID + INSTALL_IN_COMPONENT stdlib-experimental) + diff --git a/stdlib/public/Bionic/Glibc.swift b/stdlib/public/Bionic/Glibc.swift new file mode 100644 index 0000000000000..f3d608174a019 --- /dev/null +++ b/stdlib/public/Bionic/Glibc.swift @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +@_exported import SwiftBionic // Clang module + +//===----------------------------------------------------------------------===// +// sys/errno.h +//===----------------------------------------------------------------------===// + +public var errno: Int32 { + get { + return __errno_location().memory + } + set(val) { + return __errno_location().memory = val + } +} + +//===----------------------------------------------------------------------===// +// fcntl.h +//===----------------------------------------------------------------------===// + +public var S_IFMT: mode_t { return mode_t(0o170000) } +public var S_IFIFO: mode_t { return mode_t(0o010000) } +public var S_IFCHR: mode_t { return mode_t(0o020000) } +public var S_IFDIR: mode_t { return mode_t(0o040000) } +public var S_IFBLK: mode_t { return mode_t(0o060000) } +public var S_IFREG: mode_t { return mode_t(0o100000) } +public var S_IFLNK: mode_t { return mode_t(0o120000) } +public var S_IFSOCK: mode_t { return mode_t(0o140000) } + +public var S_IRWXU: mode_t { return mode_t(0o000700) } +public var S_IRUSR: mode_t { return mode_t(0o000400) } +public var S_IWUSR: mode_t { return mode_t(0o000200) } +public var S_IXUSR: mode_t { return mode_t(0o000100) } + +public var S_IRWXG: mode_t { return mode_t(0o000070) } +public var S_IRGRP: mode_t { return mode_t(0o000040) } +public var S_IWGRP: mode_t { return mode_t(0o000020) } +public var S_IXGRP: mode_t { return mode_t(0o000010) } + +public var S_IRWXO: mode_t { return mode_t(0o000007) } +public var S_IROTH: mode_t { return mode_t(0o000004) } +public var S_IWOTH: mode_t { return mode_t(0o000002) } +public var S_IXOTH: mode_t { return mode_t(0o000001) } + +public var S_ISUID: mode_t { return mode_t(0o004000) } +public var S_ISGID: mode_t { return mode_t(0o002000) } +public var S_ISVTX: mode_t { return mode_t(0o001000) } + +//===----------------------------------------------------------------------===// +// signal.h +//===----------------------------------------------------------------------===// + +#if os(Linux) +public var SIG_DFL: __sighandler_t? { return nil } +public var SIG_IGN: __sighandler_t { + return unsafeBitCast(1, __sighandler_t.self) +} +public var SIG_ERR: __sighandler_t { + return unsafeBitCast(-1, __sighandler_t.self) +} +public var SIG_HOLD: __sighandler_t { + return unsafeBitCast(2, __sighandler_t.self) +} +#endif + diff --git a/stdlib/public/Bionic/README.md b/stdlib/public/Bionic/README.md new file mode 100644 index 0000000000000..3cea043f2f1f9 --- /dev/null +++ b/stdlib/public/Bionic/README.md @@ -0,0 +1,5 @@ +This directory holds the Swift Standard Library's Glibc Module, comprised of +- The *overlay* library, which amends some APIs imported from Glibc, and +- The clang [module map](http://clang.llvm.org/docs/Modules.html) which + specifies which headers need to be imported from Glibc for bare minimum + functionality. diff --git a/stdlib/public/Bionic/module.map b/stdlib/public/Bionic/module.map new file mode 100644 index 0000000000000..4067957c16072 --- /dev/null +++ b/stdlib/public/Bionic/module.map @@ -0,0 +1,373 @@ +//===--- module.map -------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +/// This is a semi-complete modulemap that maps glibc's headers in a roughly +/// similar way to the Darwin SDK modulemap. We do not take care to list every +/// single header which may be included by a particular submodule, so there can +/// still be issues if imported into the same context as one in which someone +/// included those headers directly. +/// +/// It's not named just Glibc so that it doesn't conflict in the event of a +/// future official glibc modulemap. +module SwiftBionic [system] { + link "dl" + + // C standard library + module C { + //module complex { + // header "SYSROOT/usr/include/complex.h" + // export * + //} + module ctype { + header "SYSROOT/usr/include/ctype.h" + export * + } + module errno { + header "SYSROOT/usr/include/errno.h" + export * + } + + // glibc specific + module features { + header "SYSROOT/usr/include/features.h" + export * + } + + module fenv { + header "SYSROOT/usr/include/fenv.h" + export * + } + + // note: supplied by compiler + // module float { + // header "SYSROOT/usr/include/float.h" + // export * + // } + + module inttypes { + header "SYSROOT/usr/include/inttypes.h" + export * + } + + // note: potentially supplied by compiler + // module iso646 { + // header "SYSROOT/usr/include/iso646.h" + // export * + // } + // module limits { + // header "SYSROOT/usr/include/limits.h" + // export * + // } + + module locale { + header "SYSROOT/usr/include/locale.h" + export * + } + module math { + header "SYSROOT/usr/include/math.h" + export * + } + module setjmp { + header "SYSROOT/usr/include/setjmp.h" + export * + } + module signal { + header "SYSROOT/usr/include/signal.h" + export * + } + + // note: supplied by the compiler + // module stdarg { + // header "SYSROOT/usr/include/stdarg.h" + // export * + // } + // module stdbool { + // header "SYSROOT/usr/include/stdbool.h" + // export * + // } + // module stddef { + // header "SYSROOT/usr/include/stddef.h" + // export * + // } + // module stdint { + // header "SYSROOT/usr/include/stdint.h" + // export * + // } + + module stdio { + header "SYSROOT/usr/include/stdio.h" + export * + } + module stdlib { + header "SYSROOT/usr/include/stdlib.h" + export * + export stddef + } + module string { + header "SYSROOT/usr/include/string.h" + export * + } + + // note: supplied by the compiler + // explicit module tgmath { + // header "SYSROOT/usr/include/tgmath.h" + // export * + // } + + module time { + header "SYSROOT/usr/include/time.h" + export * + } + } + + // POSIX + module POSIX { + //module aio { + // header "SYSROOT/usr/include/aio.h" + // export * + //} + module arpa { + module inet { + header "SYSROOT/usr/include/arpa/inet.h" + export * + } + export * + } + //module cpio { + // header "SYSROOT/usr/include/cpio.h" + // export * + //} + module dirent { + header "SYSROOT/usr/include/dirent.h" + export * + } + module dlfcn { + header "SYSROOT/usr/include/dlfcn.h" + export * + } + module fcntl { + header "SYSROOT/usr/include/fcntl.h" + export * + } + //module fmtmsg { + // header "SYSROOT/usr/include/fmtmsg.h" + // export * + //} + module fnmatch { + header "SYSROOT/usr/include/fnmatch.h" + export * + } + //module ftw { + // header "SYSROOT/usr/include/ftw.h" + // export * + //} + //module glob { + // header "SYSROOT/usr/include/glob.h" + // export * + //} + module grp { + header "SYSROOT/usr/include/grp.h" + export * + } + //module iconv { + // header "SYSROOT/usr/include/iconv.h" + // export * + //} + module ioctl { + header "SYSROOT/usr/include/sys/ioctl.h" + export * + } + //module langinfo { + // header "SYSROOT/usr/include/langinfo.h" + // export * + //} + module libgen { + header "SYSROOT/usr/include/libgen.h" + export * + } + //module monetary { + // header "SYSROOT/usr/include/monetary.h" + // export * + //} + //module netdb { + // header "SYSROOT/usr/include/netdb.h" + // export * + //} + module net { + module if { + header "SYSROOT/usr/include/net/if.h" + export * + } + } + module netinet { + module in { + header "SYSROOT/usr/include/netinet/in.h" + export * + + exclude header "SYSROOT/usr/include/netinet6/in6.h" + } + module tcp { + header "SYSROOT/usr/include/netinet/tcp.h" + export * + } + } + //module nl_types { + // header "SYSROOT/usr/include/nl_types.h" + // export * + //} + module poll { + header "SYSROOT/usr/include/poll.h" + export * + } + module pthread { + header "SYSROOT/usr/include/pthread.h" + export * + } + module pwd { + header "SYSROOT/usr/include/pwd.h" + export * + } + module regex { + header "SYSROOT/usr/include/regex.h" + export * + } + module sched { + header "SYSROOT/usr/include/sched.h" + export * + } + //module search { + // header "SYSROOT/usr/include/search.h" + // export * + //} + module semaphore { + header "SYSROOT/usr/include/semaphore.h" + export * + } + //module spawn { + // header "SYSROOT/usr/include/spawn.h" + // export * + //} + module strings { + header "SYSROOT/usr/include/strings.h" + export * + } + + module sys { + export * + + module ipc { + header "SYSROOT/usr/include/sys/ipc.h" + export * + } + module mman { + header "SYSROOT/usr/include/sys/mman.h" + export * + } + //module msg { + // header "SYSROOT/usr/include/sys/msg.h" + // export * + //} + module resource { + header "SYSROOT/usr/include/sys/resource.h" + export * + } + module select { + header "SYSROOT/usr/include/sys/select.h" + export * + } + //module sem { + // header "SYSROOT/usr/include/sys/sem.h" + // export * + //} + //module shm { + // header "SYSROOT/usr/include/sys/shm.h" + // export * + //}/* + module socket { + header "SYSROOT/usr/include/sys/socket.h" + export * + } + module stat { + header "SYSROOT/usr/include/sys/stat.h" + export * + } + //module statvfs { + // header "SYSROOT/usr/include/sys/statvfs.h" + // export * + //} + module time { + header "SYSROOT/usr/include/sys/time.h" + export * + } + module times { + header "SYSROOT/usr/include/sys/times.h" + export * + } + module types { + header "SYSROOT/usr/include/sys/types.h" + export * + } + module uio { + header "SYSROOT/usr/include/sys/uio.h" + export * + } + module un { + header "SYSROOT/usr/include/sys/un.h" + export * + } + module utsname { + header "SYSROOT/usr/include/sys/utsname.h" + export * + } + module wait { + header "SYSROOT/usr/include/sys/wait.h" + export * + } + } + //module syslog { + // header "SYSROOT/usr/include/syslog.h" + // export * + //} + //module tar { + // header "SYSROOT/usr/include/tar.h" + // export * + //} + module termios { + header "SYSROOT/usr/include/termios.h" + export * + } + module ulimit { + header "SYSROOT/usr/include/ulimit.h" + export * + } + module unistd { + header "SYSROOT/usr/include/unistd.h" + export * + } + module utime { + header "SYSROOT/usr/include/utime.h" + export * + } + //module utmpx { + // header "SYSROOT/usr/include/utmpx.h" + // export * + //} + module wait { + header "SYSROOT/usr/include/wait.h" + export * + } + //module wordexp { + // header "SYSROOT/usr/include/wordexp.h" + // export * + //} + } +} diff --git a/stdlib/public/CMakeLists.txt b/stdlib/public/CMakeLists.txt index 29aae6e5def59..b0e3d7616fc6d 100644 --- a/stdlib/public/CMakeLists.txt +++ b/stdlib/public/CMakeLists.txt @@ -29,4 +29,5 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") add_subdirectory(Glibc) + add_subdirectory(Bionic) endif() diff --git a/stdlib/public/Glibc/CMakeLists.txt b/stdlib/public/Glibc/CMakeLists.txt index d7e277b69e260..63cc727662752 100644 --- a/stdlib/public/Glibc/CMakeLists.txt +++ b/stdlib/public/Glibc/CMakeLists.txt @@ -43,4 +43,5 @@ swift_install_in_component(stdlib add_swift_library(swiftGlibc IS_SDK_OVERLAY ${sources} FILE_DEPENDS copy_glibc_module "${output_dir}" + TARGET_SDKS LINUX INSTALL_IN_COMPONENT stdlib-experimental) From 2aa6ce7736e5c37dc29c949d849b5d6642a3a470 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Tue, 8 Dec 2015 22:12:28 -0500 Subject: [PATCH 08/16] android: add Android to list of possible target OSes, stdlib now compiles --- lib/Basic/LangOptions.cpp | 5 ++++- stdlib/private/StdlibUnittest/RaceTest.swift | 2 +- .../StdlibUnittest/StdlibCoreExtras.swift | 2 +- .../StdlibUnittest/StdlibUnittest.swift.gyb | 19 ++++++++++++++++++- .../SwiftPrivateDarwinExtras/Subprocess.swift | 12 +++++++++++- .../SwiftPrivateDarwinExtras.swift | 6 +++++- .../PthreadBarriers.swift | 2 +- .../SwiftPrivatePthreadExtras.swift | 2 +- stdlib/public/Bionic/Glibc.swift | 6 +++--- stdlib/public/Bionic/module.map | 16 ++++++++-------- 10 files changed, 53 insertions(+), 19 deletions(-) diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index b74a635c0fe26..63d39f686b1c2 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -29,7 +29,8 @@ const std::vector LangOptions::SupportedOSBuildConfigArguments = { "watchOS", "iOS", "Linux", - "FreeBSD" + "FreeBSD", + "Android" }; const std::vector LangOptions::SupportedArchBuildConfigArguments = { @@ -97,6 +98,8 @@ std::pair LangOptions::setTarget(llvm::Triple triple) { addTargetConfigOption("os", "watchOS"); else if (triple.isiOS()) addTargetConfigOption("os", "iOS"); + else if (triple.isAndroid()) + addTargetConfigOption("os", "Android"); else if (triple.isOSLinux()) addTargetConfigOption("os", "Linux"); else if (triple.isOSFreeBSD()) diff --git a/stdlib/private/StdlibUnittest/RaceTest.swift b/stdlib/private/StdlibUnittest/RaceTest.swift index c360a56ccccbc..ba466d71ca92d 100644 --- a/stdlib/private/StdlibUnittest/RaceTest.swift +++ b/stdlib/private/StdlibUnittest/RaceTest.swift @@ -40,7 +40,7 @@ import SwiftPrivate import SwiftPrivatePthreadExtras #if os(OSX) || os(iOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif diff --git a/stdlib/private/StdlibUnittest/StdlibCoreExtras.swift b/stdlib/private/StdlibUnittest/StdlibCoreExtras.swift index 543082859b4cc..d4928587a35f9 100644 --- a/stdlib/private/StdlibUnittest/StdlibCoreExtras.swift +++ b/stdlib/private/StdlibUnittest/StdlibCoreExtras.swift @@ -14,7 +14,7 @@ import SwiftPrivate import SwiftPrivateDarwinExtras #if os(OSX) || os(iOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb index d4b24e4b1ee60..88f1e6ec737b5 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb @@ -16,7 +16,7 @@ import SwiftPrivateDarwinExtras #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif @@ -1036,6 +1036,7 @@ public enum OSVersion : CustomStringConvertible { case watchOSSimulator case Linux case FreeBSD + case Android public var description: String { switch self { @@ -1057,6 +1058,8 @@ public enum OSVersion : CustomStringConvertible { return "Linux" case FreeBSD: return "FreeBSD" + case Android: + return "Android" } } } @@ -1091,6 +1094,8 @@ func _getOSVersion() -> OSVersion { return .Linux #elseif os(FreeBSD) return .FreeBSD +#elseif os(Android) + return .Android #else let productVersion = _stdlib_getSystemVersionPlistProperty("ProductVersion")! let (major, minor, bugFix) = _parseDottedVersionTriple(productVersion) @@ -1159,6 +1164,7 @@ public enum TestRunPredicate : CustomStringConvertible { case watchOSSimulatorAny(/*reason:*/ String) case LinuxAny(reason: String) + case AndroidAny(reason: String) case FreeBSDAny(reason: String) @@ -1232,6 +1238,9 @@ public enum TestRunPredicate : CustomStringConvertible { case FreeBSDAny(reason: let reason): return "FreeBSDAny(*, reason: \(reason))" + + case AndroidAny(reason: let reason): + return "AndroidAny(*, reason: \(reason))" } } @@ -1471,6 +1480,14 @@ public enum TestRunPredicate : CustomStringConvertible { default: return false } + + case AndroidAny: + switch _getRunningOSVersion() { + case .Android: + return true + default: + return false + } } } } diff --git a/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift b/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift index 3684ff6274cb6..b7d2d597254f1 100644 --- a/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift +++ b/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift @@ -13,10 +13,12 @@ import SwiftPrivate #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif +#if !os(Android) + // swift_posix_spawn isn't available in the public watchOS SDK, we sneak by the // unavailable attribute declaration here of the APIs that we need. @@ -47,6 +49,8 @@ func swift_posix_spawn( _ argv: UnsafePointer>, _ envp: UnsafePointer>) -> CInt +#endif + /// Calls POSIX `pipe()`. func posixPipe() -> (readFD: CInt, writeFD: CInt) { var fds: [CInt] = [ -1, -1 ] @@ -64,6 +68,9 @@ func posixPipe() -> (readFD: CInt, writeFD: CInt) { /// stderr. public func spawnChild(args: [String]) -> (pid: pid_t, stdinFD: CInt, stdoutFD: CInt, stderrFD: CInt) { +#if os(Android) + preconditionFailure("posix_spawn doesn't exist on Android") +#else var fileActions = posix_spawn_file_actions_t() if swift_posix_spawn_file_actions_init(&fileActions) != 0 { preconditionFailure("swift_posix_spawn_file_actions_init() failed") @@ -138,6 +145,7 @@ public func spawnChild(args: [String]) } return (pid, childStdin.writeFD, childStdout.readFD, childStderr.readFD) +#endif } internal func _readAll(fd: CInt) -> String { @@ -234,6 +242,8 @@ internal func _getEnviron() -> UnsafeMutablePointer> return _NSGetEnviron().memory #elseif os(FreeBSD) return environ; +#elseif os(Android) + return environ #else return __environ #endif diff --git a/stdlib/private/SwiftPrivateDarwinExtras/SwiftPrivateDarwinExtras.swift b/stdlib/private/SwiftPrivateDarwinExtras/SwiftPrivateDarwinExtras.swift index c8168921e3045..c434f4efea071 100644 --- a/stdlib/private/SwiftPrivateDarwinExtras/SwiftPrivateDarwinExtras.swift +++ b/stdlib/private/SwiftPrivateDarwinExtras/SwiftPrivateDarwinExtras.swift @@ -13,11 +13,14 @@ import SwiftPrivate #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif public func _stdlib_mkstemps(inout template: String, _ suffixlen: CInt) -> CInt { +#if os(Android) + preconditionFailure("mkstemps doesn't work on Android") +#else var utf8 = template.nulTerminatedUTF8 let (fd, fileName) = utf8.withUnsafeMutableBufferPointer { (utf8) -> (CInt, String) in @@ -27,6 +30,7 @@ public func _stdlib_mkstemps(inout template: String, _ suffixlen: CInt) -> CInt } template = fileName return fd +#endif } public var _stdlib_FD_SETSIZE: CInt { diff --git a/stdlib/private/SwiftPrivatePthreadExtras/PthreadBarriers.swift b/stdlib/private/SwiftPrivatePthreadExtras/PthreadBarriers.swift index de5d46ff02c76..ed8fe97b7c670 100644 --- a/stdlib/private/SwiftPrivatePthreadExtras/PthreadBarriers.swift +++ b/stdlib/private/SwiftPrivatePthreadExtras/PthreadBarriers.swift @@ -12,7 +12,7 @@ #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif diff --git a/stdlib/private/SwiftPrivatePthreadExtras/SwiftPrivatePthreadExtras.swift b/stdlib/private/SwiftPrivatePthreadExtras/SwiftPrivatePthreadExtras.swift index decd206477aff..9bb4e3808d5e5 100644 --- a/stdlib/private/SwiftPrivatePthreadExtras/SwiftPrivatePthreadExtras.swift +++ b/stdlib/private/SwiftPrivatePthreadExtras/SwiftPrivatePthreadExtras.swift @@ -17,7 +17,7 @@ #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) import Darwin -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) || os(FreeBSD) || os(Android) import Glibc #endif diff --git a/stdlib/public/Bionic/Glibc.swift b/stdlib/public/Bionic/Glibc.swift index f3d608174a019..f0f83fc9e81b6 100644 --- a/stdlib/public/Bionic/Glibc.swift +++ b/stdlib/public/Bionic/Glibc.swift @@ -18,10 +18,10 @@ public var errno: Int32 { get { - return __errno_location().memory + return __errno().memory } set(val) { - return __errno_location().memory = val + return __errno().memory = val } } @@ -61,7 +61,7 @@ public var S_ISVTX: mode_t { return mode_t(0o001000) } // signal.h //===----------------------------------------------------------------------===// -#if os(Linux) +#if os(Android) public var SIG_DFL: __sighandler_t? { return nil } public var SIG_IGN: __sighandler_t { return unsafeBitCast(1, __sighandler_t.self) diff --git a/stdlib/public/Bionic/module.map b/stdlib/public/Bionic/module.map index 4067957c16072..1d8e1e7e4180d 100644 --- a/stdlib/public/Bionic/module.map +++ b/stdlib/public/Bionic/module.map @@ -345,10 +345,10 @@ module SwiftBionic [system] { header "SYSROOT/usr/include/termios.h" export * } - module ulimit { - header "SYSROOT/usr/include/ulimit.h" - export * - } + //module ulimit { + // header "SYSROOT/usr/include/ulimit.h" + // export * + //} module unistd { header "SYSROOT/usr/include/unistd.h" export * @@ -361,10 +361,10 @@ module SwiftBionic [system] { // header "SYSROOT/usr/include/utmpx.h" // export * //} - module wait { - header "SYSROOT/usr/include/wait.h" - export * - } + //module wait { + // header "SYSROOT/usr/include/wait.h" + // export * + //} //module wordexp { // header "SYSROOT/usr/include/wordexp.h" // export * From eb8a8f4e53065ffa2ff61882f8ce935872b43040 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 10 Dec 2015 01:11:12 -0500 Subject: [PATCH 09/16] android: load conformance data by reading /proc/self/maps, copy swift.ld for Android target Hello world works now! --- stdlib/public/runtime/CMakeLists.txt | 3 +- stdlib/public/runtime/ProtocolConformance.cpp | 59 +++++++++++++++++-- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 80e1ce44c493e..4cc4bb0ca05e2 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -52,7 +52,7 @@ add_swift_library(swiftRuntime IS_STDLIB IS_STDLIB_CORE INSTALL_IN_COMPONENT stdlib) foreach(sdk ${SWIFT_CONFIGURED_SDKS}) - if("${sdk}" STREQUAL "LINUX" OR "${sdk}" STREQUAL "FREEBSD") + if("${sdk}" STREQUAL "LINUX" OR "${sdk}" STREQUAL "FREEBSD" OR "${sdk}" STREQUAL "ANDROID") foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}") @@ -66,6 +66,5 @@ foreach(sdk ${SWIFT_CONFIGURED_SDKS}) endforeach() endif() - # FIXME: Android: make a swift.ld for armv7 android endforeach() diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 2b829a108f23e..fdb740532c9ad 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -306,10 +306,57 @@ static void _addImageProtocolConformances(const mach_header *mh, _addImageProtocolConformancesBlock(conformances, conformancesSize); } + +#elif defined(__ANDROID__) +#include +#include +#include + +static void _addImageProtocolConformances(std::string const& name) { + // FIXME: Android: special case the current executable? + void *handle = dlopen(name.c_str(), RTLD_LAZY); + if (!handle) + return; // not a shared library + auto conformances = reinterpret_cast( + dlsym(handle, SWIFT_PROTOCOL_CONFORMANCES_SECTION)); + + if (!conformances) { + // if there are no conformances, don't hold this handle open. + dlclose(handle); + return; + } + + // Extract the size of the conformances block from the head of the section + auto conformancesSize = *reinterpret_cast(conformances); + conformances += sizeof(conformancesSize); + + _addImageProtocolConformancesBlock(conformances, conformancesSize); + + dlclose(handle); +} + +static void android_iterate_libs(void (*callback)(std::string const&)) { + std::unordered_set already; + FILE* f = fopen("/proc/self/maps", "r"); + if (!f) + return; + char name[PATH_MAX + 1]; + char perms[4 + 1]; + while (fscanf(f, " %*s %4c %*s %*s %*s%*[ ]%[^\n]", perms, name) > 0) { + if (perms[2] != 'x' || name[0] != '/') + continue; + if (strncmp(name, "/dev/", 5) == 0) + continue; + std::string name_str = name; + if (already.count(name_str) != 0) + continue; + already.insert(name_str); + callback(name_str); + } + fclose(f); +} + #elif defined(__ELF__) -#ifdef __ANDROID__ -#define RTLD_NOLOAD 0 -#endif static int _addImageProtocolConformances(struct dl_phdr_info *info, size_t size, void * /*data*/) { @@ -344,15 +391,15 @@ static void _initializeCallbacksToInspectDylib() { // Dyld will invoke this on our behalf for all images that have already // been loaded. _dyld_register_func_for_add_image(_addImageProtocolConformances); +#elif defined(__ANDROID__) + // Android only gained dl_iterate_phdr in API 21, so use /proc/self/maps + android_iterate_libs(_addImageProtocolConformances); #elif defined(__ELF__) // Search the loaded dls. Unlike the above, this only searches the already // loaded ones. // FIXME: Find a way to have this continue to happen after. // rdar://problem/19045112 - #ifndef __ANDROID__ - // FIXME: Android: doesn't have dl_iterate_phdr before API 21 dl_iterate_phdr(_addImageProtocolConformances, nullptr); - #endif #else # error No known mechanism to inspect dynamic libraries on this platform. #endif From b79d05cb3081d5903d1ba88508251b3bc0330a33 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Sat, 12 Dec 2015 15:02:18 -0500 Subject: [PATCH 10/16] android: detect NDK path from environmental variable, starting to fix Swift default linker flags, attempt at copying libicu libraries automatically (doesn't work) --- CMakeLists.txt | 8 ++++++-- cmake/modules/AddSwift.cmake | 2 +- cmake/modules/FindICU.cmake | 4 ++-- lib/Driver/Driver.cpp | 10 ++++++++++ lib/Driver/ToolChains.cpp | 25 +++++++++++++++++++++++++ stdlib/public/Bionic/CMakeLists.txt | 14 +++++++++++++- 6 files changed, 57 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed2182df166f2..a2affa5fb5381 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,7 @@ set(SWIFT_NATIVE_CLANG_TOOLS_PATH "" CACHE STRING set(SWIFT_NATIVE_SWIFT_TOOLS_PATH "" CACHE STRING "Path to the directory that contains Swift tools that are executable on the build machine") -set(SWIFT_ANDROID_NDK_PATH "/home/zhuowei/ndk" CACHE STRING +set(SWIFT_ANDROID_NDK_PATH "$ENV{ANDROID_NDK_HOME}" CACHE STRING "Path to the directory that contains the Android NDK tools that are executable on the build machine") # The following only works with the Ninja generator in CMake >= 3.0. set(SWIFT_PARALLEL_COMPILE_JOBS "" CACHE STRING @@ -427,8 +427,12 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") is_sdk_requested(ANDROID swift_build_android) if(swift_build_android AND ${swift_can_crosscompile_stdlib}) + if("${SWIFT_ANDROID_NDK_PATH}" STREQUAL "") + message(FATAL_ERROR "environmental variable ANDROID_NDK_HOME not set") + endif() configure_sdk_unix(ANDROID "Android" "android" "android" "armv7" "armv7-none-linux-androideabi") - set(SWIFT_SDK_ANDROID_PATH "/home/zhuowei/ndk/platforms/android-16/arch-arm") + set(SWIFT_SDK_ANDROID_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-16/arch-arm") + set(SWIFT_PRIMARY_VARIANT_SDK_default "ANDROID") set(SWIFT_PRIMARY_VARIANT_ARCH_default "armv7") endif() diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index dadfbfe208b8c..9561382c37c98 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -180,7 +180,7 @@ function(_add_variant_link_flags "-ldl" "-L${SWIFT_ANDROID_NDK_PATH}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.8" "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so" - "-L/home/zhuowei/libiconv-libicu-android/armeabi-v7a") + "-L${CMAKE_SOURCE_DIR}/../libiconv-libicu-android/armeabi-v7a") else() list(APPEND result "-lobjc") endif() diff --git a/cmake/modules/FindICU.cmake b/cmake/modules/FindICU.cmake index 49b31aab27ef5..c8e31e25be551 100644 --- a/cmake/modules/FindICU.cmake +++ b/cmake/modules/FindICU.cmake @@ -27,8 +27,8 @@ foreach(MODULE ${ICU_FIND_COMPONENTS}) endif() endforeach() message("FIXME Android: ICU") -set(ICU_I18N_INCLUDE_DIR "/home/zhuowei/icu/source/i18n") -set(ICU_UC_INCLUDE_DIR "/home/zhuowei/icu/source/common") +set(ICU_I18N_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/../icu/source/i18n") +set(ICU_UC_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/../icu/source/common") find_package_handle_standard_args(ICU DEFAULT_MSG ${ICU_REQUIRED}) mark_as_advanced(${ICU_REQUIRED}) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index f3ba2b9430b30..835227cabda58 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1077,6 +1077,16 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, }); } } + } else if (TC.getTriple().isAndroid()) { + const char* ndkhome = getenv("ANDROID_NDK_HOME"); + if (!ndkhome) { + llvm::errs() << + "ANDROID_NDK_HOME environmental variable not set; " + "won't be able to build Android programs. Please " + "set it to the path of the NDK\n"; + } else { + OI.SDKPath = std::string(ndkhome) + "/platforms/android-16/arch-arm"; + } } if (!OI.SDKPath.empty()) { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 25e72833ec197..b5571438b3b25 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1112,6 +1112,31 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, Arguments.push_back(context.Args.MakeArgString(LibProfile)); } + if (getTriple().isAndroid()) { + // FIXME: Android: hard-coded paths to arm; needs to fix for arm64, x86 + Arguments.push_back("-target"); + Arguments.push_back("armv7-none-linux-androideabi"); + //Arguments.push_back(context.Args.MakeArgString(getTriple().str())); + + const char* ndkhome = getenv("ANDROID_NDK_HOME"); + assert(ndkhome && "ANDROID_NDK_HOME needs to be set to NDK " + "install directory for linking"); + + auto libgccpath = Twine(ndkhome) + "/toolchains/" + "arm-linux-androideabi-4.8/prebuilt/linux-x86_64/" + "lib/gcc/arm-linux-androideabi/4.8"; + Arguments.push_back("-L"); + Arguments.push_back(context.Args.MakeArgString(libgccpath)); + + auto libcxxpath = Twine(ndkhome) + "/sources/" + "cxx-stl/llvm-libc++/libs/armeabi-v7a"; + Arguments.push_back("-L"); + Arguments.push_back(context.Args.MakeArgString(libcxxpath)); + + Arguments.push_back("-lgcc"); + Arguments.push_back("-lc"); + } + // FIXME: We probably shouldn't be adding an rpath here unless we know ahead // of time the standard library won't be copied. Arguments.push_back("-Xlinker"); diff --git a/stdlib/public/Bionic/CMakeLists.txt b/stdlib/public/Bionic/CMakeLists.txt index 492c4e7e81fc4..bf7db8bceedd5 100644 --- a/stdlib/public/Bionic/CMakeLists.txt +++ b/stdlib/public/Bionic/CMakeLists.txt @@ -14,7 +14,7 @@ foreach(input ${sources}) # "${output_dir}/${input}") list(APPEND commands COMMAND - "sed" "-e" "s@SYSROOT@/home/zhuowei/ndk/platforms/android-16/arch-arm@g" + "sed" "-e" "s@SYSROOT@${SWIFT_ANDROID_NDK_PATH}/platforms/android-16/arch-arm@g" "${CMAKE_CURRENT_SOURCE_DIR}/${input}" ">" "${output_dir}/${input}") @@ -39,3 +39,15 @@ add_swift_library(swiftGlibc IS_SDK_OVERLAY TARGET_SDKS ANDROID INSTALL_IN_COMPONENT stdlib-experimental) +# FIXME: Android: find where this belongs +set(iculibs + "${CMAKE_SOURCE_DIR}/../libiconv-libicu-android/armeabi-v7a/libicudata.so" + "${CMAKE_SOURCE_DIR}/../libiconv-libicu-android/armeabi-v7a/libicuuc.so" + "${CMAKE_SOURCE_DIR}/../libiconv-libicu-android/armeabi-v7a/libicui18n.so" +) + +# TODO: Android: copy this during build as well + +swift_install_in_component(stdlib + FILES ${iculibs} + DESTINATION "lib/swift/android/armv7") From 3a4a59d6fb89b2b98b9550496a2e280a0421ec23 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Mon, 14 Dec 2015 21:57:04 -0500 Subject: [PATCH 11/16] android: load conformance tables in main executable properly; fixes #5 --- stdlib/public/runtime/ProtocolConformance.cpp | 21 ++++++++++++++----- utils/build-script-impl | 1 - 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index fdb740532c9ad..6e38d216e111a 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -311,10 +311,10 @@ static void _addImageProtocolConformances(const mach_header *mh, #include #include #include +#include -static void _addImageProtocolConformances(std::string const& name) { - // FIXME: Android: special case the current executable? - void *handle = dlopen(name.c_str(), RTLD_LAZY); +static void _addImageProtocolConformances(const char *name) { + void *handle = dlopen(name, RTLD_LAZY); if (!handle) return; // not a shared library auto conformances = reinterpret_cast( @@ -335,11 +335,17 @@ static void _addImageProtocolConformances(std::string const& name) { dlclose(handle); } -static void android_iterate_libs(void (*callback)(std::string const&)) { +static void android_iterate_libs(void (*callback)(const char*)) { std::unordered_set already; FILE* f = fopen("/proc/self/maps", "r"); if (!f) return; + char ownname[PATH_MAX + 1]; + if (readlink("/proc/self/exe", ownname, sizeof(ownname)) == -1) { + fprintf(stderr, "swift: can't find path of executable\n"); + ownname[0] = '\0'; + } + char name[PATH_MAX + 1]; char perms[4 + 1]; while (fscanf(f, " %*s %4c %*s %*s %*s%*[ ]%[^\n]", perms, name) > 0) { @@ -351,7 +357,12 @@ static void android_iterate_libs(void (*callback)(std::string const&)) { if (already.count(name_str) != 0) continue; already.insert(name_str); - callback(name_str); + const char* libname = name_str.c_str(); + if (strcmp(libname, ownname) == 0) { + // need to pass null if opening main executable + libname = nullptr; + } + callback(libname); } fclose(f); } diff --git a/utils/build-script-impl b/utils/build-script-impl index fd6f1cbda3fb9..d7ff80b37dd0b 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -1100,7 +1100,6 @@ fi if [[ "${DISTCC}" ]] ; then BUILD_ARGS="${BUILD_ARGS} -j $(distcc -j)" fi -BUILD_ARGS="${BUILD_ARGS} -j2" case "${CMAKE_GENERATOR}" in Ninja) From 1a2490b2155b2ca139db71d6f78c68300b99f140 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 17 Dec 2015 20:56:44 -0500 Subject: [PATCH 12/16] android: add Lit config for executing tests on device --- test/lit.cfg | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/lit.cfg b/test/lit.cfg index 92a11398b392c..3d45874c743f2 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -619,6 +619,46 @@ elif run_os == 'linux-gnu' or run_os == 'linux-gnueabihf' or run_os == 'freebsd' config.target_ld = ( "ld -L%s" % (os.path.join(test_resource_dir, config.target_sdk_name))) +elif run_os == 'linux-androideabi': + # Android + lit_config.note("Testing Android " + config.variant_triple) + config.target_object_format = "elf" + config.target_runtime = "native" + config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") + config.target_sdk_name = "android" + config.target_build_swift = ( + '%s -target %s -Xlinker --allow-shlib-undefined -Xlinker -pie %s %s %s %s' + % (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt, + config.swift_test_options, swift_execution_tests_extra_flags)) + config.target_swift_frontend = ( + '%s -frontend -target %s %s' + % (config.swift, config.variant_triple, resource_dir_opt)) + subst_target_swift_frontend_mock_sdk = config.target_swift_frontend + subst_target_swift_frontend_mock_sdk_after = "" + config.target_run = config.test_source_root + \ + '/../../swift-android-extras/rundroid' + config.target_sil_opt = ( + '%s -target %s %s %s' % + (config.sil_opt, config.variant_triple, resource_dir_opt, mcp_opt)) + config.target_swift_ide_test = ( + '%s -target %s %s %s %s' % + (config.swift_ide_test, config.variant_triple, resource_dir_opt, + mcp_opt, ccp_opt)) + subst_target_swift_ide_test_mock_sdk = config.target_swift_ide_test + subst_target_swift_ide_test_mock_sdk_after = "" + config.target_swiftc_driver = ( + "%s -target %s %s %s" % + (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt)) + config.target_swift_modulewrap = ( + '%s -modulewrap -target %s' % + (config.swiftc, config.variant_triple)) + config.target_clang = ( + "clang++ -target %s %s" % + (config.variant_triple, clang_mcp_opt)) + config.target_ld = ( + "ld -L%s" % + (os.path.join(test_resource_dir, config.target_sdk_name))) + config.environment['ANDROID_NDK_HOME'] = os.getenv("ANDROID_NDK_HOME") else: lit_config.fatal("Don't know how to define target_run and " From 86d0b5f35dae2c40c9e506c2b179dbdfa67b49c0 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 17 Dec 2015 22:15:14 -0500 Subject: [PATCH 13/16] android: add unmodified posix_spawn implementation from FreeBSD for diff visibility --- stdlib/public/Bionic/posix_spawn.c | 478 +++++++++++++++++++++++++++++ stdlib/public/Bionic/spawn.h | 118 +++++++ 2 files changed, 596 insertions(+) create mode 100644 stdlib/public/Bionic/posix_spawn.c create mode 100644 stdlib/public/Bionic/spawn.h diff --git a/stdlib/public/Bionic/posix_spawn.c b/stdlib/public/Bionic/posix_spawn.c new file mode 100644 index 0000000000000..c65a730875d2f --- /dev/null +++ b/stdlib/public/Bionic/posix_spawn.c @@ -0,0 +1,478 @@ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "un-namespace.h" +#include "libc_private.h" + +extern char **environ; + +struct __posix_spawnattr { + short sa_flags; + pid_t sa_pgroup; + struct sched_param sa_schedparam; + int sa_schedpolicy; + sigset_t sa_sigdefault; + sigset_t sa_sigmask; +}; + +struct __posix_spawn_file_actions { + STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; +}; + +typedef struct __posix_spawn_file_actions_entry { + STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; + enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; + + int fae_fildes; + union { + struct { + char *path; +#define fae_path fae_data.open.path + int oflag; +#define fae_oflag fae_data.open.oflag + mode_t mode; +#define fae_mode fae_data.open.mode + } open; + struct { + int newfildes; +#define fae_newfildes fae_data.dup2.newfildes + } dup2; + } fae_data; +} posix_spawn_file_actions_entry_t; + +/* + * Spawn routines + */ + +static int +process_spawnattr(const posix_spawnattr_t sa) +{ + struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; + int i; + + /* + * POSIX doesn't really describe in which order everything + * should be set. We'll just set them in the order in which they + * are mentioned. + */ + + /* Set process group */ + if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) { + if (setpgid(0, sa->sa_pgroup) != 0) + return (errno); + } + + /* Set scheduler policy */ + if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) { + if (sched_setscheduler(0, sa->sa_schedpolicy, + &sa->sa_schedparam) != 0) + return (errno); + } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) { + if (sched_setparam(0, &sa->sa_schedparam) != 0) + return (errno); + } + + /* Reset user ID's */ + if (sa->sa_flags & POSIX_SPAWN_RESETIDS) { + if (setegid(getgid()) != 0) + return (errno); + if (seteuid(getuid()) != 0) + return (errno); + } + + /* + * Set signal masks/defaults. + * Use unwrapped syscall, libthr is in undefined state after vfork(). + */ + if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) { + __sys_sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL); + } + + if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) { + for (i = 1; i <= _SIG_MAXSIG; i++) { + if (sigismember(&sa->sa_sigdefault, i)) + if (__sys_sigaction(i, &sigact, NULL) != 0) + return (errno); + } + } + + return (0); +} + +static int +process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) +{ + int fd; + + switch (fae->fae_action) { + case FAE_OPEN: + /* Perform an open(), make it use the right fd */ + fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); + if (fd < 0) + return (errno); + if (fd != fae->fae_fildes) { + if (_dup2(fd, fae->fae_fildes) == -1) + return (errno); + if (_close(fd) != 0) { + if (errno == EBADF) + return (EBADF); + } + } + if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) + return (errno); + break; + case FAE_DUP2: + /* Perform a dup2() */ + if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) + return (errno); + if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) + return (errno); + break; + case FAE_CLOSE: + /* Perform a close(), do not fail if already closed */ + (void)_close(fae->fae_fildes); + break; + } + return (0); +} + +static int +process_file_actions(const posix_spawn_file_actions_t fa) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + /* Replay all file descriptor modifications */ + STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { + error = process_file_actions_entry(fae); + if (error) + return (error); + } + return (0); +} + +static int +do_posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *sa, + char * const argv[], char * const envp[], int use_env_path) +{ + pid_t p; + volatile int error = 0; + + p = vfork(); + switch (p) { + case -1: + return (errno); + case 0: + if (sa != NULL) { + error = process_spawnattr(*sa); + if (error) + _exit(127); + } + if (fa != NULL) { + error = process_file_actions(*fa); + if (error) + _exit(127); + } + if (use_env_path) + _execvpe(path, argv, envp != NULL ? envp : environ); + else + _execve(path, argv, envp != NULL ? envp : environ); + error = errno; + _exit(127); + default: + if (error != 0) + _waitpid(p, NULL, WNOHANG); + else if (pid != NULL) + *pid = p; + return (error); + } +} + +int +posix_spawn(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *sa, + char * const argv[], char * const envp[]) +{ + return do_posix_spawn(pid, path, fa, sa, argv, envp, 0); +} + +int +posix_spawnp(pid_t *pid, const char *path, + const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *sa, + char * const argv[], char * const envp[]) +{ + return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); +} + +/* + * File descriptor actions + */ + +int +posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret) +{ + posix_spawn_file_actions_t fa; + + fa = malloc(sizeof(struct __posix_spawn_file_actions)); + if (fa == NULL) + return (-1); + + STAILQ_INIT(&fa->fa_list); + *ret = fa; + return (0); +} + +int +posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) +{ + posix_spawn_file_actions_entry_t *fae; + + while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { + /* Remove file action entry from the queue */ + STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); + + /* Deallocate file action entry */ + if (fae->fae_action == FAE_OPEN) + free(fae->fae_path); + free(fae); + } + + free(*fa); + return (0); +} + +int +posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, + int fildes, const char * __restrict path, int oflag, mode_t mode) +{ + posix_spawn_file_actions_entry_t *fae; + int error; + + if (fildes < 0) + return (EBADF); + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_OPEN; + fae->fae_path = strdup(path); + if (fae->fae_path == NULL) { + error = errno; + free(fae); + return (error); + } + fae->fae_fildes = fildes; + fae->fae_oflag = oflag; + fae->fae_mode = mode; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +int +posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, + int fildes, int newfildes) +{ + posix_spawn_file_actions_entry_t *fae; + + if (fildes < 0 || newfildes < 0) + return (EBADF); + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_DUP2; + fae->fae_fildes = fildes; + fae->fae_newfildes = newfildes; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +int +posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, + int fildes) +{ + posix_spawn_file_actions_entry_t *fae; + + if (fildes < 0) + return (EBADF); + + /* Allocate object */ + fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); + if (fae == NULL) + return (errno); + + /* Set values and store in queue */ + fae->fae_action = FAE_CLOSE; + fae->fae_fildes = fildes; + + STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); + return (0); +} + +/* + * Spawn attributes + */ + +int +posix_spawnattr_init(posix_spawnattr_t *ret) +{ + posix_spawnattr_t sa; + + sa = calloc(1, sizeof(struct __posix_spawnattr)); + if (sa == NULL) + return (errno); + + /* Set defaults as specified by POSIX, cleared above */ + *ret = sa; + return (0); +} + +int +posix_spawnattr_destroy(posix_spawnattr_t *sa) +{ + free(*sa); + return (0); +} + +int +posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa, + short * __restrict flags) +{ + *flags = (*sa)->sa_flags; + return (0); +} + +int +posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa, + pid_t * __restrict pgroup) +{ + *pgroup = (*sa)->sa_pgroup; + return (0); +} + +int +posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa, + struct sched_param * __restrict schedparam) +{ + *schedparam = (*sa)->sa_schedparam; + return (0); +} + +int +posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa, + int * __restrict schedpolicy) +{ + *schedpolicy = (*sa)->sa_schedpolicy; + return (0); +} + +int +posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigdefault) +{ + *sigdefault = (*sa)->sa_sigdefault; + return (0); +} + +int +posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa, + sigset_t * __restrict sigmask) +{ + *sigmask = (*sa)->sa_sigmask; + return (0); +} + +int +posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) +{ + (*sa)->sa_flags = flags; + return (0); +} + +int +posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup) +{ + (*sa)->sa_pgroup = pgroup; + return (0); +} + +int +posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa, + const struct sched_param * __restrict schedparam) +{ + (*sa)->sa_schedparam = *schedparam; + return (0); +} + +int +posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy) +{ + (*sa)->sa_schedpolicy = schedpolicy; + return (0); +} + +int +posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigdefault) +{ + (*sa)->sa_sigdefault = *sigdefault; + return (0); +} + +int +posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa, + const sigset_t * __restrict sigmask) +{ + (*sa)->sa_sigmask = *sigmask; + return (0); +} diff --git a/stdlib/public/Bionic/spawn.h b/stdlib/public/Bionic/spawn.h new file mode 100644 index 0000000000000..7889d0e102469 --- /dev/null +++ b/stdlib/public/Bionic/spawn.h @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2008 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SPAWN_H_ +#define _SPAWN_H_ + +#include +#include +#include + +#ifndef _MODE_T_DECLARED +typedef __mode_t mode_t; +#define _MODE_T_DECLARED +#endif + +#ifndef _PID_T_DECLARED +typedef __pid_t pid_t; +#define _PID_T_DECLARED +#endif + +#ifndef _SIGSET_T_DECLARED +#define _SIGSET_T_DECLARED +typedef __sigset_t sigset_t; +#endif + +struct sched_param; + +typedef struct __posix_spawnattr *posix_spawnattr_t; +typedef struct __posix_spawn_file_actions *posix_spawn_file_actions_t; + +#define POSIX_SPAWN_RESETIDS 0x01 +#define POSIX_SPAWN_SETPGROUP 0x02 +#define POSIX_SPAWN_SETSCHEDPARAM 0x04 +#define POSIX_SPAWN_SETSCHEDULER 0x08 +#define POSIX_SPAWN_SETSIGDEF 0x10 +#define POSIX_SPAWN_SETSIGMASK 0x20 + +__BEGIN_DECLS +/* + * Spawn routines + * + * XXX both arrays should be __restrict, but this does not work when GCC + * is invoked with -std=c99. + */ +int posix_spawn(pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restrict, + char * const [], char * const []); +int posix_spawnp(pid_t * __restrict, const char * __restrict, + const posix_spawn_file_actions_t *, const posix_spawnattr_t * __restrict, + char * const [], char * const []); + +/* + * File descriptor actions + */ +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict, + int, const char * __restrict, int, mode_t); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); + +/* + * Spawn attributes + */ +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); + +int posix_spawnattr_getflags(const posix_spawnattr_t * __restrict, + short * __restrict); +int posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict, + pid_t * __restrict); +int posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict, + struct sched_param * __restrict); +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict, + int * __restrict); +int posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict, + sigset_t * __restrict); +int posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict, + sigset_t * __restrict sigmask); + +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); +int posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict, + const struct sched_param * __restrict); +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); +int posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict, + const sigset_t * __restrict); +int posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict, + const sigset_t * __restrict); +__END_DECLS + +#endif /* !_SPAWN_H_ */ From 6d6a59bf1aff12ed3a1881ccd8e0e33c6d6209a1 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 17 Dec 2015 22:16:37 -0500 Subject: [PATCH 14/16] android: add a modified FreeBSD posix_spawn --- .../SwiftPrivateDarwinExtras/Subprocess.swift | 7 +--- stdlib/public/Bionic/CMakeLists.txt | 2 ++ stdlib/public/Bionic/module.map | 4 +++ stdlib/public/Bionic/posix_spawn.c | 33 +++++++++---------- stdlib/public/Bionic/spawn.h | 19 ++--------- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift b/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift index b7d2d597254f1..a2ee199a94459 100644 --- a/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift +++ b/stdlib/private/SwiftPrivateDarwinExtras/Subprocess.swift @@ -17,7 +17,7 @@ import Darwin import Glibc #endif -#if !os(Android) +// FIXME: Android: prefix with swift_ in Android version // swift_posix_spawn isn't available in the public watchOS SDK, we sneak by the // unavailable attribute declaration here of the APIs that we need. @@ -49,7 +49,6 @@ func swift_posix_spawn( _ argv: UnsafePointer>, _ envp: UnsafePointer>) -> CInt -#endif /// Calls POSIX `pipe()`. func posixPipe() -> (readFD: CInt, writeFD: CInt) { @@ -68,9 +67,6 @@ func posixPipe() -> (readFD: CInt, writeFD: CInt) { /// stderr. public func spawnChild(args: [String]) -> (pid: pid_t, stdinFD: CInt, stdoutFD: CInt, stderrFD: CInt) { -#if os(Android) - preconditionFailure("posix_spawn doesn't exist on Android") -#else var fileActions = posix_spawn_file_actions_t() if swift_posix_spawn_file_actions_init(&fileActions) != 0 { preconditionFailure("swift_posix_spawn_file_actions_init() failed") @@ -145,7 +141,6 @@ public func spawnChild(args: [String]) } return (pid, childStdin.writeFD, childStdout.readFD, childStderr.readFD) -#endif } internal func _readAll(fd: CInt) -> String { diff --git a/stdlib/public/Bionic/CMakeLists.txt b/stdlib/public/Bionic/CMakeLists.txt index bf7db8bceedd5..4c3b3d78e77f8 100644 --- a/stdlib/public/Bionic/CMakeLists.txt +++ b/stdlib/public/Bionic/CMakeLists.txt @@ -1,5 +1,6 @@ set(sources module.map + spawn.h ) set(output_dir "${SWIFTLIB_DIR}/bionic") @@ -35,6 +36,7 @@ swift_install_in_component(stdlib add_swift_library(swiftGlibc IS_SDK_OVERLAY Glibc.swift + posix_spawn.c FILE_DEPENDS copy_bionic_module "${SWIFTLIB_DIR}/bionic" TARGET_SDKS ANDROID INSTALL_IN_COMPONENT stdlib-experimental) diff --git a/stdlib/public/Bionic/module.map b/stdlib/public/Bionic/module.map index 1d8e1e7e4180d..80d400d245752 100644 --- a/stdlib/public/Bionic/module.map +++ b/stdlib/public/Bionic/module.map @@ -369,5 +369,9 @@ module SwiftBionic [system] { // header "SYSROOT/usr/include/wordexp.h" // export * //} + module spawn { + header "spawn.h" + export * + } } } diff --git a/stdlib/public/Bionic/posix_spawn.c b/stdlib/public/Bionic/posix_spawn.c index c65a730875d2f..4cea37f41c313 100644 --- a/stdlib/public/Bionic/posix_spawn.c +++ b/stdlib/public/Bionic/posix_spawn.c @@ -27,20 +27,17 @@ #include __FBSDID("$FreeBSD$"); -#include "namespace.h" #include #include #include #include #include -#include +#include "spawn.h" #include #include #include #include -#include "un-namespace.h" -#include "libc_private.h" extern char **environ; @@ -85,6 +82,7 @@ typedef struct __posix_spawn_file_actions_entry { static int process_spawnattr(const posix_spawnattr_t sa) { +#if 0 struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; int i; @@ -133,6 +131,7 @@ process_spawnattr(const posix_spawnattr_t sa) return (errno); } } +#endif return (0); } @@ -145,30 +144,30 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae) switch (fae->fae_action) { case FAE_OPEN: /* Perform an open(), make it use the right fd */ - fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode); + fd = open(fae->fae_path, fae->fae_oflag, fae->fae_mode); if (fd < 0) return (errno); if (fd != fae->fae_fildes) { - if (_dup2(fd, fae->fae_fildes) == -1) + if (dup2(fd, fae->fae_fildes) == -1) return (errno); - if (_close(fd) != 0) { + if (close(fd) != 0) { if (errno == EBADF) return (EBADF); } } - if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1) + if (fcntl(fae->fae_fildes, F_SETFD, 0) == -1) return (errno); break; case FAE_DUP2: /* Perform a dup2() */ - if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1) + if (dup2(fae->fae_fildes, fae->fae_newfildes) == -1) return (errno); - if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) + if (fcntl(fae->fae_newfildes, F_SETFD, 0) == -1) return (errno); break; case FAE_CLOSE: /* Perform a close(), do not fail if already closed */ - (void)_close(fae->fae_fildes); + (void)close(fae->fae_fildes); break; } return (0); @@ -198,7 +197,7 @@ do_posix_spawn(pid_t *pid, const char *path, pid_t p; volatile int error = 0; - p = vfork(); + p = fork(); switch (p) { case -1: return (errno); @@ -213,15 +212,15 @@ do_posix_spawn(pid_t *pid, const char *path, if (error) _exit(127); } - if (use_env_path) - _execvpe(path, argv, envp != NULL ? envp : environ); - else - _execve(path, argv, envp != NULL ? envp : environ); + //if (use_env_path) + // execvpe(path, argv, envp != NULL ? envp : environ); + //else + execve(path, argv, envp != NULL ? envp : environ); error = errno; _exit(127); default: if (error != 0) - _waitpid(p, NULL, WNOHANG); + waitpid(p, NULL, WNOHANG); else if (pid != NULL) *pid = p; return (error); diff --git a/stdlib/public/Bionic/spawn.h b/stdlib/public/Bionic/spawn.h index 7889d0e102469..e144a895ea3cd 100644 --- a/stdlib/public/Bionic/spawn.h +++ b/stdlib/public/Bionic/spawn.h @@ -30,23 +30,8 @@ #define _SPAWN_H_ #include -#include -#include - -#ifndef _MODE_T_DECLARED -typedef __mode_t mode_t; -#define _MODE_T_DECLARED -#endif - -#ifndef _PID_T_DECLARED -typedef __pid_t pid_t; -#define _PID_T_DECLARED -#endif - -#ifndef _SIGSET_T_DECLARED -#define _SIGSET_T_DECLARED -typedef __sigset_t sigset_t; -#endif +#include +#include struct sched_param; From 1b61ae794fee44ce1cd14943965c22195fb723ab Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 17 Dec 2015 23:48:09 -0500 Subject: [PATCH 15/16] android: do not add rpaths when linking the dynamic linker doesn't understand them and spams warnings. --- cmake/modules/AddSwift.cmake | 2 +- lib/Driver/ToolChains.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 9561382c37c98..2d3ebbc1f79a8 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -922,7 +922,7 @@ function(_add_swift_library_single target name) set_target_properties("${target}" PROPERTIES INSTALL_NAME_DIR "${install_name_dir}") - elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND NOT "${SWIFTLIB_SINGLE_SDK}" STREQUAL "ANDROID") set_target_properties("${target}" PROPERTIES INSTALL_RPATH "$ORIGIN:/usr/lib/swift/linux") diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index b5571438b3b25..cc33384b66f6a 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1135,15 +1135,17 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, Arguments.push_back("-lgcc"); Arguments.push_back("-lc"); + } else { + // rpaths are not supported on Android. + + // FIXME: We probably shouldn't be adding an rpath here unless we know ahead + // of time the standard library won't be copied. + Arguments.push_back("-Xlinker"); + Arguments.push_back("-rpath"); + Arguments.push_back("-Xlinker"); + Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); } - // FIXME: We probably shouldn't be adding an rpath here unless we know ahead - // of time the standard library won't be copied. - Arguments.push_back("-Xlinker"); - Arguments.push_back("-rpath"); - Arguments.push_back("-Xlinker"); - Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); - // Always add the stdlib Arguments.push_back("-lswiftCore"); From f88771a24306ab936d338d0522510a75ca117676 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Wed, 6 Jan 2016 20:33:47 -0500 Subject: [PATCH 16/16] android: Use Android bionic's arc4random_uniform (which isn't in headers but is available on all versions so far) --- stdlib/public/stubs/LibcShims.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp index f4e9df966297a..5f6a40e0a4dc6 100644 --- a/stdlib/public/stubs/LibcShims.cpp +++ b/stdlib/public/stubs/LibcShims.cpp @@ -30,6 +30,8 @@ static_assert(std::is_same::value, #ifdef __ANDROID__ extern "C" { extern size_t dlmalloc_usable_size(void*); +// arc4random_random is missing in headers but does exist +extern unsigned int arc4random_uniform(unsigned int upper_bound); } #endif @@ -78,21 +80,12 @@ size_t _swift_stdlib_malloc_size(const void *ptr) { #error No malloc_size analog known for this platform/libc. #endif -#ifndef __ANDROID__ __swift_uint32_t _swift_stdlib_arc4random(void) { return arc4random(); } __swift_uint32_t _swift_stdlib_arc4random_uniform(__swift_uint32_t upper_bound) { return arc4random_uniform(upper_bound); } -#else -// FIXME: Android: chosen by fair dice roll -__swift_uint32_t _swift_stdlib_arc4random(void) { return 4; } -__swift_uint32_t -_swift_stdlib_arc4random_uniform(__swift_uint32_t upper_bound) { - return 0; -} -#endif } // namespace swift