Files
swift-mirror/stdlib/public/stubs/LibcShims.cpp
Michael Ilseman 5eb5e34897 [stdlib] Shims for UBreakIterator and thread local storage.
Introduce shims for using UBreakIterators from ICU. Also introduce
shims for using thread local storage via pthreads.

We will be relying on ICU and UBreakIterators for grapheme
breaking. But, UBreakIterators are very expensive to create,
especially for the way we do grapheme breaking, which is relatively
stateless. Thus, we will stash one or more into thread local storage
and reset it as needed.

Note: Currently, pthread_key_t is hard coded for a single platform
(Darwin), but I have a static_assert alongside directions on how to
adapt it to any future platforms who differ in key type.
2017-05-16 20:28:31 -07:00

180 lines
4.9 KiB
C++

//===--- LibcShims.cpp ----------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include <random>
#include <type_traits>
#include <cmath>
#if defined(_WIN32)
#include <io.h>
#else
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "swift/Basic/Lazy.h"
#include "../SwiftShims/LibcShims.h"
#include "llvm/Support/DataTypes.h"
using namespace swift;
static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value,
"__swift_ssize_t must be defined as equivalent to ssize_t");
SWIFT_RUNTIME_STDLIB_INTERFACE
void swift::_swift_stdlib_free(void *ptr) {
free(ptr);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_putchar_unlocked(int c) {
#if defined(_WIN32)
return _putc_nolock(c, stdout);
#else
return putchar_unlocked(c);
#endif
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_size_t swift::_swift_stdlib_fwrite_stdout(const void *ptr,
__swift_size_t size,
__swift_size_t nitems) {
return fwrite(ptr, size, nitems, stdout);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_size_t swift::_swift_stdlib_strlen(const char *s) {
return strlen(s);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_size_t swift::_swift_stdlib_strlen_unsigned(const unsigned char *s) {
return strlen((char *)s);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_memcmp(const void *s1, const void *s2,
__swift_size_t n) {
return memcmp(s1, s2, n);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_ssize_t
swift::_swift_stdlib_read(int fd, void *buf, __swift_size_t nbyte) {
#if defined(_WIN32)
return _read(fd, buf, nbyte);
#else
return read(fd, buf, nbyte);
#endif
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_ssize_t
swift::_swift_stdlib_write(int fd, const void *buf, __swift_size_t nbyte) {
#if defined(_WIN32)
return _write(fd, buf, nbyte);
#else
return write(fd, buf, nbyte);
#endif
}
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_close(int fd) {
#if defined(_WIN32)
return _close(fd);
#else
return close(fd);
#endif
}
// Guard compilation on the typedef for __swift_pthread_key_t in LibcShims.h
// being identical to the platform's pthread_key_t
static_assert(std::is_same<__swift_pthread_key_t, pthread_key_t>::value,
"This platform's pthread_key_t differs. If you hit this assert, "
"fix __swift_pthread_key_t's typedef in LibcShims.h by adding an "
"#if guard and definition for your platform");
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_key_create(
__swift_pthread_key_t * _Nonnull key,
void (* _Nullable destructor)(void *)
) {
return pthread_key_create(key, destructor);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable swift::_swift_stdlib_pthread_getspecific(
__swift_pthread_key_t key
) {
return pthread_getspecific(key);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_setspecific(
__swift_pthread_key_t key, const void * _Nullable value
) {
return pthread_setspecific(key, value);
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_pthread_key_t _swift_stdlib_PTHREAD_KEYS_MAX(void) {
return PTHREAD_KEYS_MAX;
}
#if defined(__APPLE__)
#include <malloc/malloc.h>
SWIFT_RUNTIME_STDLIB_INTERFACE
size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
return malloc_size(ptr);
}
#elif defined(__GNU_LIBRARY__) || defined(__CYGWIN__) || defined(__ANDROID__)
#include <malloc.h>
SWIFT_RUNTIME_STDLIB_INTERFACE
size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
return malloc_usable_size(const_cast<void *>(ptr));
}
#elif defined(_WIN32)
#include <malloc.h>
SWIFT_RUNTIME_STDLIB_INTERFACE
size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
return _msize(const_cast<void *>(ptr));
}
#elif defined(__FreeBSD__)
#include <malloc_np.h>
SWIFT_RUNTIME_STDLIB_INTERFACE
size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
return malloc_usable_size(const_cast<void *>(ptr));
}
#else
#error No malloc_size analog known for this platform/libc.
#endif
static Lazy<std::mt19937> theGlobalMT19937;
static std::mt19937 &getGlobalMT19937() {
return theGlobalMT19937.get();
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_uint32_t swift::_swift_stdlib_cxx11_mt19937() {
return getGlobalMT19937()();
}
SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_uint32_t
swift::_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
if (upper_bound > 0)
upper_bound--;
std::uniform_int_distribution<__swift_uint32_t> RandomUniform(0, upper_bound);
return RandomUniform(getGlobalMT19937());
}