Merge llvm, clang, lld, lldb, compiler-rt and libc++ r302418, and update
build glue.
This commit is contained in:
commit
0f5676f432
@ -15,10 +15,11 @@
|
||||
#define XRAY_XRAY_INTERFACE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stddef.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Synchronize this with AsmPrinter::SledKind in LLVM.
|
||||
/// Synchronize this with AsmPrinter::SledKind in LLVM.
|
||||
enum XRayEntryType {
|
||||
ENTRY = 0,
|
||||
EXIT = 1,
|
||||
@ -26,32 +27,43 @@ enum XRayEntryType {
|
||||
LOG_ARGS_ENTRY = 3,
|
||||
};
|
||||
|
||||
// Provide a function to invoke for when instrumentation points are hit. This is
|
||||
// a user-visible control surface that overrides the default implementation. The
|
||||
// function provided should take the following arguments:
|
||||
//
|
||||
// - function id: an identifier that indicates the id of a function; this id
|
||||
// is generated by xray; the mapping between the function id
|
||||
// and the actual function pointer is available through
|
||||
// __xray_table.
|
||||
// - entry type: identifies what kind of instrumentation point was encountered
|
||||
// (function entry, function exit, etc.). See the enum
|
||||
// XRayEntryType for more details.
|
||||
//
|
||||
// The user handler must handle correctly spurious calls after this handler is
|
||||
// removed or replaced with another handler, because it would be too costly for
|
||||
// XRay runtime to avoid spurious calls.
|
||||
// To prevent circular calling, the handler function itself and all its
|
||||
// direct&indirect callees must not be instrumented with XRay, which can be
|
||||
// achieved by marking them all with: __attribute__((xray_never_instrument))
|
||||
//
|
||||
// Returns 1 on success, 0 on error.
|
||||
/// Provide a function to invoke for when instrumentation points are hit. This
|
||||
/// is a user-visible control surface that overrides the default implementation.
|
||||
/// The function provided should take the following arguments:
|
||||
///
|
||||
/// - function id: an identifier that indicates the id of a function; this id
|
||||
/// is generated by xray; the mapping between the function id
|
||||
/// and the actual function pointer is available through
|
||||
/// __xray_table.
|
||||
/// - entry type: identifies what kind of instrumentation point was
|
||||
/// encountered (function entry, function exit, etc.). See the
|
||||
/// enum XRayEntryType for more details.
|
||||
///
|
||||
/// The user handler must handle correctly spurious calls after this handler is
|
||||
/// removed or replaced with another handler, because it would be too costly for
|
||||
/// XRay runtime to avoid spurious calls.
|
||||
/// To prevent circular calling, the handler function itself and all its
|
||||
/// direct&indirect callees must not be instrumented with XRay, which can be
|
||||
/// achieved by marking them all with: __attribute__((xray_never_instrument))
|
||||
///
|
||||
/// Returns 1 on success, 0 on error.
|
||||
extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));
|
||||
|
||||
// This removes whatever the currently provided handler is. Returns 1 on
|
||||
// success, 0 on error.
|
||||
/// This removes whatever the currently provided handler is. Returns 1 on
|
||||
/// success, 0 on error.
|
||||
extern int __xray_remove_handler();
|
||||
|
||||
/// Use XRay to log the first argument of each (instrumented) function call.
|
||||
/// When this function exits, all threads will have observed the effect and
|
||||
/// start logging their subsequent affected function calls (if patched).
|
||||
///
|
||||
/// Returns 1 on success, 0 on error.
|
||||
extern int __xray_set_handler_arg1(void (*)(int32_t, XRayEntryType, uint64_t));
|
||||
|
||||
/// Disables the XRay handler used to log first arguments of function calls.
|
||||
/// Returns 1 on success, 0 on error.
|
||||
extern int __xray_remove_handler_arg1();
|
||||
|
||||
enum XRayPatchingStatus {
|
||||
NOT_INITIALIZED = 0,
|
||||
SUCCESS = 1,
|
||||
@ -59,24 +71,31 @@ enum XRayPatchingStatus {
|
||||
FAILED = 3,
|
||||
};
|
||||
|
||||
// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
|
||||
// for possible result values.
|
||||
/// This tells XRay to patch the instrumentation points. See XRayPatchingStatus
|
||||
/// for possible result values.
|
||||
extern XRayPatchingStatus __xray_patch();
|
||||
|
||||
// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
|
||||
// result values.
|
||||
/// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible
|
||||
/// result values.
|
||||
extern XRayPatchingStatus __xray_unpatch();
|
||||
|
||||
// Use XRay to log the first argument of each (instrumented) function call.
|
||||
// When this function exits, all threads will have observed the effect and
|
||||
// start logging their subsequent affected function calls (if patched).
|
||||
//
|
||||
// Returns 1 on success, 0 on error.
|
||||
extern int __xray_set_handler_arg1(void (*)(int32_t, XRayEntryType, uint64_t));
|
||||
/// This patches a specific function id. See XRayPatchingStatus for possible
|
||||
/// result values.
|
||||
extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);
|
||||
|
||||
/// This unpatches a specific function id. See XRayPatchingStatus for possible
|
||||
/// result values.
|
||||
extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);
|
||||
|
||||
/// This function returns the address of the function provided a valid function
|
||||
/// id. We return 0 if we encounter any error, even if 0 may be a valid function
|
||||
/// address.
|
||||
extern uintptr_t __xray_function_address(int32_t FuncId);
|
||||
|
||||
/// This function returns the maximum valid function id. Returns 0 if we
|
||||
/// encounter errors (when there are no instrumented functions, etc.).
|
||||
extern size_t __xray_max_function_id();
|
||||
|
||||
// Disables the XRay handler used to log first arguments of function calls.
|
||||
// Returns 1 on success, 0 on error.
|
||||
extern int __xray_remove_handler_arg1();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -443,6 +443,13 @@ INTERCEPTOR(void, _longjmp, void *env, int val) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT___LONGJMP_CHK
|
||||
INTERCEPTOR(void, __longjmp_chk, void *env, int val) {
|
||||
__asan_handle_no_return();
|
||||
REAL(__longjmp_chk)(env, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASAN_INTERCEPT_SIGLONGJMP
|
||||
INTERCEPTOR(void, siglongjmp, void *env, int val) {
|
||||
__asan_handle_no_return();
|
||||
@ -758,6 +765,9 @@ void InitializeAsanInterceptors() {
|
||||
#if ASAN_INTERCEPT__LONGJMP
|
||||
ASAN_INTERCEPT_FUNC(_longjmp);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT___LONGJMP_CHK
|
||||
ASAN_INTERCEPT_FUNC(__longjmp_chk);
|
||||
#endif
|
||||
#if ASAN_INTERCEPT_SIGLONGJMP
|
||||
ASAN_INTERCEPT_FUNC(siglongjmp);
|
||||
#endif
|
||||
|
@ -58,6 +58,12 @@
|
||||
# define ASAN_INTERCEPT_SIGLONGJMP 0
|
||||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
# define ASAN_INTERCEPT___LONGJMP_CHK 1
|
||||
#else
|
||||
# define ASAN_INTERCEPT___LONGJMP_CHK 0
|
||||
#endif
|
||||
|
||||
// Android bug: https://code.google.com/p/android/issues/detail?id=61799
|
||||
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && \
|
||||
!(SANITIZER_ANDROID && defined(__i386))
|
||||
|
@ -98,7 +98,7 @@ static __inline emutls_address_array* emutls_getspecific() {
|
||||
|
||||
#else
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
@ -60,9 +60,7 @@ typedef union
|
||||
}s;
|
||||
} udwords;
|
||||
|
||||
/* MIPS64 issue: PR 20098 */
|
||||
#if (defined(__LP64__) || defined(__wasm__)) && \
|
||||
!(defined(__mips__) && defined(__clang__))
|
||||
#if (defined(__LP64__) || defined(__wasm__) || defined(__mips64))
|
||||
#define CRT_HAS_128BIT
|
||||
#endif
|
||||
|
||||
|
@ -24,3 +24,8 @@ fun:_ZNSt3__19addressof*
|
||||
# Windows C++ stdlib headers that contain bad unrelated casts.
|
||||
src:*xmemory0
|
||||
src:*xstddef
|
||||
|
||||
# std::_Sp_counted_ptr_inplace::_Sp_counted_ptr_inplace() (libstdc++).
|
||||
# This ctor is used by std::make_shared and needs to cast to uninitialized T*
|
||||
# in order to call std::allocator_traits<T>::construct.
|
||||
fun:_ZNSt23_Sp_counted_ptr_inplace*
|
||||
|
@ -368,11 +368,12 @@ struct ScudoAllocator {
|
||||
void *Ptr;
|
||||
uptr Salt;
|
||||
uptr AllocationAlignment = FromPrimary ? MinAlignment : Alignment;
|
||||
ScudoThreadContext *ThreadContext = getThreadContext();
|
||||
ScudoThreadContext *ThreadContext = getThreadContextAndLock();
|
||||
if (LIKELY(ThreadContext)) {
|
||||
Salt = getPrng(ThreadContext)->getNext();
|
||||
Ptr = BackendAllocator.Allocate(getAllocatorCache(ThreadContext),
|
||||
NeededSize, AllocationAlignment);
|
||||
ThreadContext->unlock();
|
||||
} else {
|
||||
SpinMutexLock l(&FallbackMutex);
|
||||
Salt = FallbackPrng.getNext();
|
||||
@ -434,9 +435,10 @@ struct ScudoAllocator {
|
||||
if (BypassQuarantine) {
|
||||
Chunk->eraseHeader();
|
||||
void *Ptr = Chunk->getAllocBeg(Header);
|
||||
ScudoThreadContext *ThreadContext = getThreadContext();
|
||||
ScudoThreadContext *ThreadContext = getThreadContextAndLock();
|
||||
if (LIKELY(ThreadContext)) {
|
||||
getBackendAllocator().Deallocate(getAllocatorCache(ThreadContext), Ptr);
|
||||
ThreadContext->unlock();
|
||||
} else {
|
||||
SpinMutexLock Lock(&FallbackMutex);
|
||||
getBackendAllocator().Deallocate(&FallbackAllocatorCache, Ptr);
|
||||
@ -445,12 +447,13 @@ struct ScudoAllocator {
|
||||
UnpackedHeader NewHeader = *Header;
|
||||
NewHeader.State = ChunkQuarantine;
|
||||
Chunk->compareExchangeHeader(&NewHeader, Header);
|
||||
ScudoThreadContext *ThreadContext = getThreadContext();
|
||||
ScudoThreadContext *ThreadContext = getThreadContextAndLock();
|
||||
if (LIKELY(ThreadContext)) {
|
||||
AllocatorQuarantine.Put(getQuarantineCache(ThreadContext),
|
||||
QuarantineCallback(
|
||||
getAllocatorCache(ThreadContext)),
|
||||
Chunk, Size);
|
||||
ThreadContext->unlock();
|
||||
} else {
|
||||
SpinMutexLock l(&FallbackMutex);
|
||||
AllocatorQuarantine.Put(&FallbackQuarantineCache,
|
||||
|
@ -72,7 +72,13 @@ const uptr AlignedChunkHeaderSize =
|
||||
|
||||
#if SANITIZER_CAN_USE_ALLOCATOR64
|
||||
const uptr AllocatorSpace = ~0ULL;
|
||||
const uptr AllocatorSize = 0x40000000000ULL; // 4TB.
|
||||
# if defined(__aarch64__) && SANITIZER_ANDROID
|
||||
const uptr AllocatorSize = 0x4000000000ULL; // 256G.
|
||||
# elif defined(__aarch64__)
|
||||
const uptr AllocatorSize = 0x10000000000ULL; // 1T.
|
||||
# else
|
||||
const uptr AllocatorSize = 0x40000000000ULL; // 4T.
|
||||
# endif
|
||||
typedef DefaultSizeClassMap SizeClassMap;
|
||||
struct AP {
|
||||
static const uptr kSpaceBeg = AllocatorSpace;
|
||||
|
@ -19,10 +19,16 @@
|
||||
#include "scudo_allocator.h"
|
||||
#include "scudo_utils.h"
|
||||
|
||||
#include "sanitizer_common/sanitizer_linux.h"
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
namespace __scudo {
|
||||
|
||||
struct ALIGNED(64) ScudoThreadContext {
|
||||
public:
|
||||
// Platform specific base thread context definitions.
|
||||
#include "scudo_tls_context_android.inc"
|
||||
#include "scudo_tls_context_linux.inc"
|
||||
|
||||
struct ALIGNED(64) ScudoThreadContext : public ScudoThreadContextPlatform {
|
||||
AllocatorCache Cache;
|
||||
Xorshift128Plus Prng;
|
||||
uptr QuarantineCachePlaceHolder[4];
|
||||
@ -32,8 +38,9 @@ struct ALIGNED(64) ScudoThreadContext {
|
||||
|
||||
void initThread();
|
||||
|
||||
// Fastpath functions are defined in the following platform specific headers.
|
||||
#include "scudo_tls_linux.h"
|
||||
// Platform specific dastpath functions definitions.
|
||||
#include "scudo_tls_android.inc"
|
||||
#include "scudo_tls_linux.inc"
|
||||
|
||||
} // namespace __scudo
|
||||
|
||||
|
95
contrib/compiler-rt/lib/scudo/scudo_tls_android.cpp
Normal file
95
contrib/compiler-rt/lib/scudo/scudo_tls_android.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//===-- scudo_tls_android.cpp -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// Scudo thread local structure implementation for Android.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_LINUX && SANITIZER_ANDROID
|
||||
|
||||
#include "scudo_tls.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace __scudo {
|
||||
|
||||
static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
|
||||
static pthread_key_t PThreadKey;
|
||||
|
||||
static atomic_uint32_t ThreadContextCurrentIndex;
|
||||
static ScudoThreadContext *ThreadContexts;
|
||||
static uptr NumberOfContexts;
|
||||
|
||||
// sysconf(_SC_NPROCESSORS_{CONF,ONLN}) cannot be used as they allocate memory.
|
||||
static uptr getNumberOfCPUs() {
|
||||
cpu_set_t CPUs;
|
||||
CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0);
|
||||
return CPU_COUNT(&CPUs);
|
||||
}
|
||||
|
||||
static void initOnce() {
|
||||
// Hack: TLS_SLOT_TSAN was introduced in N. To be able to use it on M for
|
||||
// testing, we create an unused key. Since the key_data array follows the tls
|
||||
// array, it basically gives us the extra entry we need.
|
||||
// TODO(kostyak): remove and restrict to N and above.
|
||||
CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0);
|
||||
initScudo();
|
||||
NumberOfContexts = getNumberOfCPUs();
|
||||
ThreadContexts = reinterpret_cast<ScudoThreadContext *>(
|
||||
MmapOrDie(sizeof(ScudoThreadContext) * NumberOfContexts, __func__));
|
||||
for (int i = 0; i < NumberOfContexts; i++)
|
||||
ThreadContexts[i].init();
|
||||
}
|
||||
|
||||
void initThread() {
|
||||
pthread_once(&GlobalInitialized, initOnce);
|
||||
// Initial context assignment is done in a plain round-robin fashion.
|
||||
u32 Index = atomic_fetch_add(&ThreadContextCurrentIndex, 1,
|
||||
memory_order_relaxed);
|
||||
ScudoThreadContext *ThreadContext =
|
||||
&ThreadContexts[Index % NumberOfContexts];
|
||||
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
|
||||
}
|
||||
|
||||
ScudoThreadContext *getThreadContextAndLockSlow() {
|
||||
ScudoThreadContext *ThreadContext;
|
||||
// Go through all the contexts and find the first unlocked one.
|
||||
for (u32 i = 0; i < NumberOfContexts; i++) {
|
||||
ThreadContext = &ThreadContexts[i];
|
||||
if (ThreadContext->tryLock()) {
|
||||
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
|
||||
return ThreadContext;
|
||||
}
|
||||
}
|
||||
// No luck, find the one with the lowest precedence, and slow lock it.
|
||||
u64 Precedence = UINT64_MAX;
|
||||
for (u32 i = 0; i < NumberOfContexts; i++) {
|
||||
u64 SlowLockPrecedence = ThreadContexts[i].getSlowLockPrecedence();
|
||||
if (SlowLockPrecedence && SlowLockPrecedence < Precedence) {
|
||||
ThreadContext = &ThreadContexts[i];
|
||||
Precedence = SlowLockPrecedence;
|
||||
}
|
||||
}
|
||||
if (LIKELY(Precedence != UINT64_MAX)) {
|
||||
ThreadContext->lock();
|
||||
*get_android_tls_ptr() = reinterpret_cast<uptr>(ThreadContext);
|
||||
return ThreadContext;
|
||||
}
|
||||
// Last resort (can this happen?), stick with the current one.
|
||||
ThreadContext =
|
||||
reinterpret_cast<ScudoThreadContext *>(*get_android_tls_ptr());
|
||||
ThreadContext->lock();
|
||||
return ThreadContext;
|
||||
}
|
||||
|
||||
} // namespace __scudo
|
||||
|
||||
#endif // SANITIZER_LINUX && SANITIZER_ANDROID
|
44
contrib/compiler-rt/lib/scudo/scudo_tls_android.inc
Normal file
44
contrib/compiler-rt/lib/scudo/scudo_tls_android.inc
Normal file
@ -0,0 +1,44 @@
|
||||
//===-- scudo_tls_android.inc -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// Scudo thread local structure fastpath functions implementation for Android.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_TLS_ANDROID_H_
|
||||
#define SCUDO_TLS_ANDROID_H_
|
||||
|
||||
#ifndef SCUDO_TLS_H_
|
||||
# error "This file must be included inside scudo_tls.h."
|
||||
#endif // SCUDO_TLS_H_
|
||||
|
||||
#if SANITIZER_LINUX && SANITIZER_ANDROID
|
||||
|
||||
ALWAYS_INLINE void initThreadMaybe() {
|
||||
if (LIKELY(*get_android_tls_ptr()))
|
||||
return;
|
||||
initThread();
|
||||
}
|
||||
|
||||
ScudoThreadContext *getThreadContextAndLockSlow();
|
||||
|
||||
ALWAYS_INLINE ScudoThreadContext *getThreadContextAndLock() {
|
||||
ScudoThreadContext *ThreadContext =
|
||||
reinterpret_cast<ScudoThreadContext *>(*get_android_tls_ptr());
|
||||
CHECK(ThreadContext);
|
||||
// Try to lock the currently associated context.
|
||||
if (ThreadContext->tryLock())
|
||||
return ThreadContext;
|
||||
// If it failed, go the slow path.
|
||||
return getThreadContextAndLockSlow();
|
||||
}
|
||||
|
||||
#endif // SANITIZER_LINUX && SANITIZER_ANDROID
|
||||
|
||||
#endif // SCUDO_TLS_ANDROID_H_
|
54
contrib/compiler-rt/lib/scudo/scudo_tls_context_android.inc
Normal file
54
contrib/compiler-rt/lib/scudo/scudo_tls_context_android.inc
Normal file
@ -0,0 +1,54 @@
|
||||
//===-- scudo_tls_context_android.inc ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// Android specific base thread context definition.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_TLS_CONTEXT_ANDROID_INC_
|
||||
#define SCUDO_TLS_CONTEXT_ANDROID_INC_
|
||||
|
||||
#ifndef SCUDO_TLS_H_
|
||||
# error "This file must be included inside scudo_tls.h."
|
||||
#endif // SCUDO_TLS_H_
|
||||
|
||||
#if SANITIZER_LINUX && SANITIZER_ANDROID
|
||||
|
||||
struct ScudoThreadContextPlatform {
|
||||
INLINE bool tryLock() {
|
||||
if (Mutex.TryLock()) {
|
||||
atomic_store_relaxed(&SlowLockPrecedence, 0);
|
||||
return true;
|
||||
}
|
||||
if (atomic_load_relaxed(&SlowLockPrecedence) == 0)
|
||||
atomic_store_relaxed(&SlowLockPrecedence, NanoTime());
|
||||
return false;
|
||||
}
|
||||
|
||||
INLINE void lock() {
|
||||
Mutex.Lock();
|
||||
atomic_store_relaxed(&SlowLockPrecedence, 0);
|
||||
}
|
||||
|
||||
INLINE void unlock() {
|
||||
Mutex.Unlock();
|
||||
}
|
||||
|
||||
INLINE u64 getSlowLockPrecedence() {
|
||||
return atomic_load_relaxed(&SlowLockPrecedence);
|
||||
}
|
||||
|
||||
private:
|
||||
StaticSpinMutex Mutex;
|
||||
atomic_uint64_t SlowLockPrecedence;
|
||||
};
|
||||
|
||||
#endif // SANITIZER_LINUX && SANITIZER_ANDROID
|
||||
|
||||
#endif // SCUDO_TLS_CONTEXT_ANDROID_INC_
|
29
contrib/compiler-rt/lib/scudo/scudo_tls_context_linux.inc
Normal file
29
contrib/compiler-rt/lib/scudo/scudo_tls_context_linux.inc
Normal file
@ -0,0 +1,29 @@
|
||||
//===-- scudo_tls_context_linux.inc -----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// Linux specific base thread context definition.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_TLS_CONTEXT_LINUX_INC_
|
||||
#define SCUDO_TLS_CONTEXT_LINUX_INC_
|
||||
|
||||
#ifndef SCUDO_TLS_H_
|
||||
# error "This file must be included inside scudo_tls.h."
|
||||
#endif // SCUDO_TLS_H_
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
struct ScudoThreadContextPlatform {
|
||||
ALWAYS_INLINE void unlock() {}
|
||||
};
|
||||
|
||||
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
#endif // SCUDO_TLS_CONTEXT_LINUX_INC_
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
#include "scudo_tls.h"
|
||||
|
||||
@ -26,8 +26,10 @@ namespace __scudo {
|
||||
static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
|
||||
static pthread_key_t PThreadKey;
|
||||
|
||||
thread_local ThreadState ScudoThreadState = ThreadNotInitialized;
|
||||
thread_local ScudoThreadContext ThreadLocalContext;
|
||||
__attribute__((tls_model("initial-exec")))
|
||||
THREADLOCAL ThreadState ScudoThreadState = ThreadNotInitialized;
|
||||
__attribute__((tls_model("initial-exec")))
|
||||
THREADLOCAL ScudoThreadContext ThreadLocalContext;
|
||||
|
||||
static void teardownThread(void *Ptr) {
|
||||
uptr Iteration = reinterpret_cast<uptr>(Ptr);
|
||||
@ -59,4 +61,4 @@ void initThread() {
|
||||
|
||||
} // namespace __scudo
|
||||
|
||||
#endif // SANITIZER_LINUX
|
||||
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- scudo_tls_linux.h ---------------------------------------*- C++ -*-===//
|
||||
//===-- scudo_tls_linux.inc -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -19,17 +19,17 @@
|
||||
# error "This file must be included inside scudo_tls.h."
|
||||
#endif // SCUDO_TLS_H_
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
enum ThreadState : u8 {
|
||||
ThreadNotInitialized = 0,
|
||||
ThreadInitialized,
|
||||
ThreadTornDown,
|
||||
};
|
||||
extern thread_local ThreadState ScudoThreadState;
|
||||
extern thread_local ScudoThreadContext ThreadLocalContext;
|
||||
__attribute__((tls_model("initial-exec")))
|
||||
extern THREADLOCAL ThreadState ScudoThreadState;
|
||||
__attribute__((tls_model("initial-exec")))
|
||||
extern THREADLOCAL ScudoThreadContext ThreadLocalContext;
|
||||
|
||||
ALWAYS_INLINE void initThreadMaybe() {
|
||||
if (LIKELY(ScudoThreadState != ThreadNotInitialized))
|
||||
@ -37,12 +37,12 @@ ALWAYS_INLINE void initThreadMaybe() {
|
||||
initThread();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE ScudoThreadContext *getThreadContext() {
|
||||
ALWAYS_INLINE ScudoThreadContext *getThreadContextAndLock() {
|
||||
if (UNLIKELY(ScudoThreadState == ThreadTornDown))
|
||||
return nullptr;
|
||||
return &ThreadLocalContext;
|
||||
}
|
||||
|
||||
#endif // SANITIZER_LINUX
|
||||
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
||||
#endif // SCUDO_TLS_LINUX_H_
|
37
contrib/compiler-rt/lib/ubsan/ubsan_diag_standalone.cc
Normal file
37
contrib/compiler-rt/lib/ubsan/ubsan_diag_standalone.cc
Normal file
@ -0,0 +1,37 @@
|
||||
//===-- ubsan_diag_standalone.cc ------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Diagnostic reporting for the standalone UBSan runtime.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ubsan_platform.h"
|
||||
#if CAN_SANITIZE_UB
|
||||
#include "ubsan_diag.h"
|
||||
|
||||
using namespace __ubsan;
|
||||
|
||||
extern "C" {
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __sanitizer_print_stack_trace() {
|
||||
uptr top = 0;
|
||||
uptr bottom = 0;
|
||||
bool request_fast_unwind = common_flags()->fast_unwind_on_fatal;
|
||||
if (request_fast_unwind)
|
||||
__sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom);
|
||||
|
||||
GET_REPORT_OPTIONS(false);
|
||||
BufferedStackTrace stack;
|
||||
stack.Unwind(kStackTraceMax, Opts.pc, Opts.bp, nullptr, top, bottom,
|
||||
request_fast_unwind);
|
||||
stack.Print();
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
#endif // CAN_SANITIZE_UB
|
@ -410,7 +410,8 @@ static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
|
||||
SourceLocation Loc = Data->Loc.acquire();
|
||||
// This check could be more precise if we used different handlers for
|
||||
// -fsanitize=bool and -fsanitize=enum.
|
||||
bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'"));
|
||||
bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
|
||||
(0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
|
||||
ErrorType ET =
|
||||
IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
|
||||
|
||||
|
@ -25,6 +25,8 @@ extern "C" {
|
||||
void __xray_init();
|
||||
extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));
|
||||
extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));
|
||||
extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak));
|
||||
extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak));
|
||||
}
|
||||
|
||||
using namespace __xray;
|
||||
@ -55,6 +57,8 @@ void __xray_init() XRAY_NEVER_INSTRUMENT {
|
||||
__sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
|
||||
XRayInstrMap.Sleds = __start_xray_instr_map;
|
||||
XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;
|
||||
XRayInstrMap.SledsIndex = __start_xray_fn_idx;
|
||||
XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx;
|
||||
}
|
||||
__sanitizer::atomic_store(&XRayInitialized, true,
|
||||
__sanitizer::memory_order_release);
|
||||
|
@ -132,12 +132,48 @@ CleanupInvoker<Function> scopeCleanup(Function Fn) XRAY_NEVER_INSTRUMENT {
|
||||
return CleanupInvoker<Function>{Fn};
|
||||
}
|
||||
|
||||
inline bool patchSled(const XRaySledEntry &Sled, bool Enable,
|
||||
int32_t FuncId) XRAY_NEVER_INSTRUMENT {
|
||||
// While we're here, we should patch the nop sled. To do that we mprotect
|
||||
// the page containing the function to be writeable.
|
||||
const uint64_t PageSize = GetPageSizeCached();
|
||||
void *PageAlignedAddr =
|
||||
reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));
|
||||
std::size_t MProtectLen = (Sled.Address + cSledLength) -
|
||||
reinterpret_cast<uint64_t>(PageAlignedAddr);
|
||||
MProtectHelper Protector(PageAlignedAddr, MProtectLen);
|
||||
if (Protector.MakeWriteable() == -1) {
|
||||
printf("Failed mprotect: %d\n", errno);
|
||||
return XRayPatchingStatus::FAILED;
|
||||
}
|
||||
|
||||
bool Success = false;
|
||||
switch (Sled.Kind) {
|
||||
case XRayEntryType::ENTRY:
|
||||
Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);
|
||||
break;
|
||||
case XRayEntryType::EXIT:
|
||||
Success = patchFunctionExit(Enable, FuncId, Sled);
|
||||
break;
|
||||
case XRayEntryType::TAIL:
|
||||
Success = patchFunctionTailExit(Enable, FuncId, Sled);
|
||||
break;
|
||||
case XRayEntryType::LOG_ARGS_ENTRY:
|
||||
Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);
|
||||
break;
|
||||
default:
|
||||
Report("Unsupported sled kind '%d' @%04x\n", Sled.Address, int(Sled.Kind));
|
||||
return false;
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
// controlPatching implements the common internals of the patching/unpatching
|
||||
// implementation. |Enable| defines whether we're enabling or disabling the
|
||||
// runtime XRay instrumentation.
|
||||
XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
|
||||
if (!__sanitizer::atomic_load(&XRayInitialized,
|
||||
__sanitizer::memory_order_acquire))
|
||||
__sanitizer::memory_order_acquire))
|
||||
return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
|
||||
|
||||
uint8_t NotPatching = false;
|
||||
@ -179,38 +215,7 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {
|
||||
++FuncId;
|
||||
CurFun = F;
|
||||
}
|
||||
|
||||
// While we're here, we should patch the nop sled. To do that we mprotect
|
||||
// the page containing the function to be writeable.
|
||||
void *PageAlignedAddr =
|
||||
reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));
|
||||
std::size_t MProtectLen = (Sled.Address + cSledLength) -
|
||||
reinterpret_cast<uint64_t>(PageAlignedAddr);
|
||||
MProtectHelper Protector(PageAlignedAddr, MProtectLen);
|
||||
if (Protector.MakeWriteable() == -1) {
|
||||
printf("Failed mprotect: %d\n", errno);
|
||||
return XRayPatchingStatus::FAILED;
|
||||
}
|
||||
|
||||
bool Success = false;
|
||||
switch (Sled.Kind) {
|
||||
case XRayEntryType::ENTRY:
|
||||
Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);
|
||||
break;
|
||||
case XRayEntryType::EXIT:
|
||||
Success = patchFunctionExit(Enable, FuncId, Sled);
|
||||
break;
|
||||
case XRayEntryType::TAIL:
|
||||
Success = patchFunctionTailExit(Enable, FuncId, Sled);
|
||||
break;
|
||||
case XRayEntryType::LOG_ARGS_ENTRY:
|
||||
Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);
|
||||
break;
|
||||
default:
|
||||
Report("Unsupported sled kind: %d\n", int(Sled.Kind));
|
||||
continue;
|
||||
}
|
||||
(void)Success;
|
||||
patchSled(Sled, Enable, FuncId);
|
||||
}
|
||||
__sanitizer::atomic_store(&XRayPatching, false,
|
||||
__sanitizer::memory_order_release);
|
||||
@ -226,6 +231,64 @@ XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT {
|
||||
return controlPatching(false);
|
||||
}
|
||||
|
||||
XRayPatchingStatus patchFunction(int32_t FuncId,
|
||||
bool Enable) XRAY_NEVER_INSTRUMENT {
|
||||
if (!__sanitizer::atomic_load(&XRayInitialized,
|
||||
__sanitizer::memory_order_acquire))
|
||||
return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.
|
||||
|
||||
uint8_t NotPatching = false;
|
||||
if (!__sanitizer::atomic_compare_exchange_strong(
|
||||
&XRayPatching, &NotPatching, true, __sanitizer::memory_order_acq_rel))
|
||||
return XRayPatchingStatus::ONGOING; // Already patching.
|
||||
|
||||
// Next, we look for the function index.
|
||||
XRaySledMap InstrMap;
|
||||
{
|
||||
__sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
|
||||
InstrMap = XRayInstrMap;
|
||||
}
|
||||
|
||||
// If we don't have an index, we can't patch individual functions.
|
||||
if (InstrMap.Functions == 0)
|
||||
return XRayPatchingStatus::NOT_INITIALIZED;
|
||||
|
||||
// FuncId must be a positive number, less than the number of functions
|
||||
// instrumented.
|
||||
if (FuncId <= 0 || static_cast<size_t>(FuncId) > InstrMap.Functions) {
|
||||
Report("Invalid function id provided: %d\n", FuncId);
|
||||
return XRayPatchingStatus::FAILED;
|
||||
}
|
||||
|
||||
// Now we patch ths sleds for this specific function.
|
||||
auto SledRange = InstrMap.SledsIndex[FuncId - 1];
|
||||
auto *f = SledRange.Begin;
|
||||
auto *e = SledRange.End;
|
||||
|
||||
bool SucceedOnce = false;
|
||||
while (f != e)
|
||||
SucceedOnce |= patchSled(*f++, Enable, FuncId);
|
||||
|
||||
__sanitizer::atomic_store(&XRayPatching, false,
|
||||
__sanitizer::memory_order_release);
|
||||
|
||||
if (!SucceedOnce) {
|
||||
Report("Failed patching any sled for function '%d'.", FuncId);
|
||||
return XRayPatchingStatus::FAILED;
|
||||
}
|
||||
|
||||
return XRayPatchingStatus::SUCCESS;
|
||||
}
|
||||
|
||||
XRayPatchingStatus __xray_patch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
|
||||
return patchFunction(FuncId, true);
|
||||
}
|
||||
|
||||
XRayPatchingStatus
|
||||
__xray_unpatch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
|
||||
return patchFunction(FuncId, false);
|
||||
}
|
||||
|
||||
int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t)) {
|
||||
if (!__sanitizer::atomic_load(&XRayInitialized,
|
||||
__sanitizer::memory_order_acquire))
|
||||
@ -239,3 +302,15 @@ int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t)) {
|
||||
return 1;
|
||||
}
|
||||
int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); }
|
||||
|
||||
uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT {
|
||||
__sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
|
||||
if (FuncId <= 0 || static_cast<size_t>(FuncId) > XRayInstrMap.Functions)
|
||||
return 0;
|
||||
return XRayInstrMap.SledsIndex[FuncId - 1].Begin->Address;
|
||||
}
|
||||
|
||||
size_t __xray_max_function_id() XRAY_NEVER_INSTRUMENT {
|
||||
__sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);
|
||||
return XRayInstrMap.Functions;
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ struct XRaySledEntry {
|
||||
#error "Unsupported word size."
|
||||
#endif
|
||||
};
|
||||
|
||||
struct XRayFunctionSledIndex {
|
||||
const XRaySledEntry* Begin;
|
||||
const XRaySledEntry* End;
|
||||
};
|
||||
}
|
||||
|
||||
namespace __xray {
|
||||
@ -46,6 +51,8 @@ namespace __xray {
|
||||
struct XRaySledMap {
|
||||
const XRaySledEntry *Sleds;
|
||||
size_t Entries;
|
||||
const XRayFunctionSledIndex *SledsIndex;
|
||||
size_t Functions;
|
||||
};
|
||||
|
||||
bool patchFunctionEntry(bool Enable, uint32_t FuncId,
|
||||
|
@ -314,7 +314,7 @@ typedef __char32_t char32_t;
|
||||
#define _LIBCPP_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#if !(__has_feature(cxx_rtti))
|
||||
#if !(__has_feature(cxx_rtti)) && !defined(_LIBCPP_NO_RTTI)
|
||||
#define _LIBCPP_NO_RTTI
|
||||
#endif
|
||||
|
||||
@ -1089,6 +1089,13 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
# define _LIBCPP_DIAGNOSE_ERROR(...)
|
||||
#endif
|
||||
|
||||
#if __has_attribute(fallthough) || _GNUC_VER >= 700
|
||||
// Use a function like macro to imply that it must be followed by a semicolon
|
||||
#define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__))
|
||||
#else
|
||||
#define _LIBCPP_FALLTHROUGH() ((void)0)
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT) && \
|
||||
(defined(_LIBCPP_COMPILER_MSVC) || __has_declspec_attribute(empty_bases))
|
||||
# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
|
||||
@ -1113,4 +1120,77 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
// Decide whether to use availability macros.
|
||||
#if !defined(_LIBCPP_BUILDING_LIBRARY) && \
|
||||
!defined(_LIBCPP_DISABLE_AVAILABILITY) && \
|
||||
__has_feature(attribute_availability_with_strict) && \
|
||||
__has_feature(attribute_availability_in_templates)
|
||||
#ifdef __APPLE__
|
||||
#define _LIBCPP_USE_AVAILABILITY_APPLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define availability macros.
|
||||
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
|
||||
#define _LIBCPP_AVAILABILITY_SHARED_MUTEX \
|
||||
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=3.0)))
|
||||
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
|
||||
#define _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH __attribute__((unavailable))
|
||||
#define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \
|
||||
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=3.0)))
|
||||
#define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \
|
||||
__attribute__((availability(macosx,strict,introduced=10.12))) \
|
||||
__attribute__((availability(ios,strict,introduced=10.0))) \
|
||||
__attribute__((availability(tvos,strict,introduced=10.0))) \
|
||||
__attribute__((availability(watchos,strict,introduced=3.0)))
|
||||
#define _LIBCPP_AVAILABILITY_FUTURE_ERROR \
|
||||
__attribute__((availability(ios,strict,introduced=6.0)))
|
||||
#define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \
|
||||
__attribute__((availability(macosx,strict,introduced=10.9))) \
|
||||
__attribute__((availability(ios,strict,introduced=7.0)))
|
||||
#define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \
|
||||
__attribute__((availability(macosx,strict,introduced=10.9))) \
|
||||
__attribute__((availability(ios,strict,introduced=7.0)))
|
||||
#define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \
|
||||
__attribute__((availability(macosx,strict,introduced=10.9))) \
|
||||
__attribute__((availability(ios,strict,introduced=7.0)))
|
||||
#else
|
||||
#define _LIBCPP_AVAILABILITY_SHARED_MUTEX
|
||||
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
#define _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
#define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS
|
||||
#define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE
|
||||
#define _LIBCPP_AVAILABILITY_FUTURE_ERROR
|
||||
#define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
|
||||
#define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY
|
||||
#define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
#endif
|
||||
|
||||
// Define availability that depends on _LIBCPP_NO_EXCEPTIONS.
|
||||
#ifdef _LIBCPP_NO_EXCEPTIONS
|
||||
#define _LIBCPP_AVAILABILITY_DYNARRAY
|
||||
#define _LIBCPP_AVAILABILITY_FUTURE
|
||||
#else
|
||||
#define _LIBCPP_AVAILABILITY_DYNARRAY _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
#define _LIBCPP_AVAILABILITY_FUTURE _LIBCPP_AVAILABILITY_FUTURE_ERROR
|
||||
#endif
|
||||
|
||||
// Availability of stream API in the dylib got dropped and re-added. The
|
||||
// extern template should effectively be available at:
|
||||
// availability(macosx,introduced=10.9)
|
||||
// availability(ios,introduced=7.0)
|
||||
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE) && \
|
||||
((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1090) || \
|
||||
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ <= 70000))
|
||||
#define _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_CONFIG
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
class _LIBCPP_TYPE_VIS id;
|
||||
|
||||
typedef int category;
|
||||
_LIBCPP_AVAILABILITY_LOCALE_CATEGORY
|
||||
static const category // values assigned here are for exposition only
|
||||
none = 0,
|
||||
collate = LC_COLLATE_MASK,
|
||||
|
@ -474,7 +474,10 @@ int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
|
||||
timeout_ms.count() > 0 ? timeout_ms.count()
|
||||
: 0,
|
||||
0))
|
||||
return GetLastError();
|
||||
{
|
||||
auto __ec = GetLastError();
|
||||
return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,30 +127,33 @@ _LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
|
||||
_LIBCPP_FUNC_VIS int uncaught_exceptions() _NOEXCEPT;
|
||||
_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT;
|
||||
|
||||
class _LIBCPP_TYPE_VIS exception_ptr;
|
||||
|
||||
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
|
||||
|
||||
#ifndef _LIBCPP_ABI_MICROSOFT
|
||||
|
||||
class _LIBCPP_TYPE_VIS exception_ptr
|
||||
{
|
||||
void* __ptr_;
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
|
||||
_LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
|
||||
|
||||
exception_ptr(const exception_ptr&) _NOEXCEPT;
|
||||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
|
||||
~exception_ptr() _NOEXCEPT;
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_EXPLICIT
|
||||
operator bool() const _NOEXCEPT {return __ptr_ != nullptr;}
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
|
||||
{return __ptr_ != nullptr;}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
|
||||
{return __x.__ptr_ == __y.__ptr_;}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
|
||||
{return !(__x == __y);}
|
||||
@ -178,6 +181,54 @@ make_exception_ptr(_Ep __e) _NOEXCEPT
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // _LIBCPP_ABI_MICROSOFT
|
||||
|
||||
class _LIBCPP_TYPE_VIS exception_ptr
|
||||
{
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#endif
|
||||
void* __ptr1_;
|
||||
void* __ptr2_;
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
public:
|
||||
exception_ptr() _NOEXCEPT;
|
||||
exception_ptr(nullptr_t) _NOEXCEPT;
|
||||
exception_ptr(const exception_ptr& __other) _NOEXCEPT;
|
||||
exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
|
||||
exception_ptr& operator=(nullptr_t) _NOEXCEPT;
|
||||
~exception_ptr() _NOEXCEPT;
|
||||
_LIBCPP_EXPLICIT operator bool() const _NOEXCEPT;
|
||||
};
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
|
||||
{return !(__x == __y);}
|
||||
|
||||
_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT;
|
||||
|
||||
_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr);
|
||||
_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
|
||||
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p);
|
||||
|
||||
// This is a built-in template function which automagically extracts the required
|
||||
// information.
|
||||
template <class _E> void *__GetExceptionInfo(_E);
|
||||
|
||||
template<class _Ep>
|
||||
exception_ptr
|
||||
make_exception_ptr(_Ep __e) _NOEXCEPT
|
||||
{
|
||||
return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_ABI_MICROSOFT
|
||||
// nested_exception
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI nested_exception
|
||||
|
@ -110,7 +110,7 @@ public:
|
||||
namespace std { namespace experimental { inline namespace __array_extensions_v1 {
|
||||
|
||||
template <class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS dynarray
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_DYNARRAY dynarray
|
||||
{
|
||||
public:
|
||||
// types:
|
||||
|
@ -145,7 +145,7 @@ namespace std { namespace experimental { inline namespace fundamentals_v1 {
|
||||
#include <stdexcept>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
|
||||
class _LIBCPP_EXCEPTION_ABI bad_optional_access
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access
|
||||
: public std::logic_error
|
||||
{
|
||||
public:
|
||||
@ -523,6 +523,9 @@ public:
|
||||
constexpr explicit operator bool() const noexcept {return this->__engaged_;}
|
||||
|
||||
_LIBCPP_NORETURN _LIBCPP_INLINE_VISIBILITY
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
#endif
|
||||
constexpr void __throw_bad_optional_access() const
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
@ -532,7 +535,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
constexpr value_type const& value() const
|
||||
{
|
||||
if (!this->__engaged_)
|
||||
@ -540,7 +543,7 @@ public:
|
||||
return this->__val_;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
value_type& value()
|
||||
{
|
||||
if (!this->__engaged_)
|
||||
|
@ -2224,7 +2224,7 @@ typename __bind_return<_Fp, _BoundArgs, _Args>::type
|
||||
__apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>,
|
||||
_Args&& __args)
|
||||
{
|
||||
return __invoke(__f, __mu(_VSTD::get<_Indx>(__bound_args), __args)...);
|
||||
return _VSTD::__invoke(__f, _VSTD::__mu(_VSTD::get<_Indx>(__bound_args), __args)...);
|
||||
}
|
||||
|
||||
template<class _Fp, class ..._BoundArgs>
|
||||
@ -2257,7 +2257,7 @@ public:
|
||||
typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
|
||||
operator()(_Args&& ...__args)
|
||||
{
|
||||
return __apply_functor(__f_, __bound_args_, __indices(),
|
||||
return _VSTD::__apply_functor(__f_, __bound_args_, __indices(),
|
||||
tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
|
||||
}
|
||||
|
||||
@ -2266,7 +2266,7 @@ public:
|
||||
typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type
|
||||
operator()(_Args&& ...__args) const
|
||||
{
|
||||
return __apply_functor(__f_, __bound_args_, __indices(),
|
||||
return _VSTD::__apply_functor(__f_, __bound_args_, __indices(),
|
||||
tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
|
||||
}
|
||||
};
|
||||
|
@ -499,7 +499,7 @@ make_error_condition(future_errc __e) _NOEXCEPT
|
||||
return error_condition(static_cast<int>(__e), future_category());
|
||||
}
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI future_error
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error
|
||||
: public logic_error
|
||||
{
|
||||
error_code __ec_;
|
||||
@ -515,6 +515,9 @@ public:
|
||||
};
|
||||
|
||||
_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
_LIBCPP_AVAILABILITY_FUTURE_ERROR
|
||||
#endif
|
||||
void __throw_future_error(future_errc _Ev)
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
@ -525,7 +528,7 @@ void __throw_future_error(future_errc _Ev)
|
||||
#endif
|
||||
}
|
||||
|
||||
class _LIBCPP_TYPE_VIS __assoc_sub_state
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state
|
||||
: public __shared_count
|
||||
{
|
||||
protected:
|
||||
@ -612,7 +615,7 @@ __assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) c
|
||||
}
|
||||
|
||||
template <class _Rp>
|
||||
class __assoc_state
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __assoc_state
|
||||
: public __assoc_sub_state
|
||||
{
|
||||
typedef __assoc_sub_state base;
|
||||
@ -652,6 +655,7 @@ __assoc_state<_Rp>::__on_zero_shared() _NOEXCEPT
|
||||
|
||||
template <class _Rp>
|
||||
template <class _Arg>
|
||||
_LIBCPP_AVAILABILITY_FUTURE
|
||||
void
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
__assoc_state<_Rp>::set_value(_Arg&& __arg)
|
||||
@ -707,7 +711,7 @@ __assoc_state<_Rp>::copy()
|
||||
}
|
||||
|
||||
template <class _Rp>
|
||||
class __assoc_state<_Rp&>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __assoc_state<_Rp&>
|
||||
: public __assoc_sub_state
|
||||
{
|
||||
typedef __assoc_sub_state base;
|
||||
@ -767,7 +771,7 @@ __assoc_state<_Rp&>::copy()
|
||||
}
|
||||
|
||||
template <class _Rp, class _Alloc>
|
||||
class __assoc_state_alloc
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc
|
||||
: public __assoc_state<_Rp>
|
||||
{
|
||||
typedef __assoc_state<_Rp> base;
|
||||
@ -795,7 +799,7 @@ __assoc_state_alloc<_Rp, _Alloc>::__on_zero_shared() _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _Rp, class _Alloc>
|
||||
class __assoc_state_alloc<_Rp&, _Alloc>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc<_Rp&, _Alloc>
|
||||
: public __assoc_state<_Rp&>
|
||||
{
|
||||
typedef __assoc_state<_Rp&> base;
|
||||
@ -821,7 +825,7 @@ __assoc_state_alloc<_Rp&, _Alloc>::__on_zero_shared() _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _Alloc>
|
||||
class __assoc_sub_state_alloc
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state_alloc
|
||||
: public __assoc_sub_state
|
||||
{
|
||||
typedef __assoc_sub_state base;
|
||||
@ -847,7 +851,7 @@ __assoc_sub_state_alloc<_Alloc>::__on_zero_shared() _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _Rp, class _Fp>
|
||||
class __deferred_assoc_state
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state
|
||||
: public __assoc_state<_Rp>
|
||||
{
|
||||
typedef __assoc_state<_Rp> base;
|
||||
@ -894,7 +898,7 @@ __deferred_assoc_state<_Rp, _Fp>::__execute()
|
||||
}
|
||||
|
||||
template <class _Fp>
|
||||
class __deferred_assoc_state<void, _Fp>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __deferred_assoc_state<void, _Fp>
|
||||
: public __assoc_sub_state
|
||||
{
|
||||
typedef __assoc_sub_state base;
|
||||
@ -942,7 +946,7 @@ __deferred_assoc_state<void, _Fp>::__execute()
|
||||
}
|
||||
|
||||
template <class _Rp, class _Fp>
|
||||
class __async_assoc_state
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state
|
||||
: public __assoc_state<_Rp>
|
||||
{
|
||||
typedef __assoc_state<_Rp> base;
|
||||
@ -997,7 +1001,7 @@ __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT
|
||||
}
|
||||
|
||||
template <class _Fp>
|
||||
class __async_assoc_state<void, _Fp>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state<void, _Fp>
|
||||
: public __assoc_sub_state
|
||||
{
|
||||
typedef __assoc_sub_state base;
|
||||
@ -1076,7 +1080,7 @@ __make_async_assoc_state(_Fp __f);
|
||||
#endif
|
||||
|
||||
template <class _Rp>
|
||||
class _LIBCPP_TEMPLATE_VIS future
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future
|
||||
{
|
||||
__assoc_state<_Rp>* __state_;
|
||||
|
||||
@ -1179,7 +1183,7 @@ future<_Rp>::get()
|
||||
}
|
||||
|
||||
template <class _Rp>
|
||||
class _LIBCPP_TEMPLATE_VIS future<_Rp&>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&>
|
||||
{
|
||||
__assoc_state<_Rp&>* __state_;
|
||||
|
||||
@ -1277,7 +1281,7 @@ future<_Rp&>::get()
|
||||
}
|
||||
|
||||
template <>
|
||||
class _LIBCPP_TYPE_VIS future<void>
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future<void>
|
||||
{
|
||||
__assoc_sub_state* __state_;
|
||||
|
||||
@ -1360,7 +1364,7 @@ swap(future<_Rp>& __x, future<_Rp>& __y) _NOEXCEPT
|
||||
template <class _Callable> class packaged_task;
|
||||
|
||||
template <class _Rp>
|
||||
class _LIBCPP_TEMPLATE_VIS promise
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise
|
||||
{
|
||||
__assoc_state<_Rp>* __state_;
|
||||
|
||||
@ -1527,7 +1531,7 @@ promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p)
|
||||
// promise<R&>
|
||||
|
||||
template <class _Rp>
|
||||
class _LIBCPP_TEMPLATE_VIS promise<_Rp&>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&>
|
||||
{
|
||||
__assoc_state<_Rp&>* __state_;
|
||||
|
||||
@ -1663,7 +1667,7 @@ promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p)
|
||||
// promise<void>
|
||||
|
||||
template <>
|
||||
class _LIBCPP_TYPE_VIS promise<void>
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<void>
|
||||
{
|
||||
__assoc_sub_state* __state_;
|
||||
|
||||
@ -1749,7 +1753,7 @@ template <class _Rp, class _Alloc>
|
||||
template<class _Fp> class __packaged_task_base;
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __packaged_task_base<_Rp(_ArgTypes...)>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_base<_Rp(_ArgTypes...)>
|
||||
{
|
||||
__packaged_task_base(const __packaged_task_base&);
|
||||
__packaged_task_base& operator=(const __packaged_task_base&);
|
||||
@ -1767,7 +1771,7 @@ public:
|
||||
template<class _FD, class _Alloc, class _FB> class __packaged_task_func;
|
||||
|
||||
template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
|
||||
class __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>
|
||||
: public __packaged_task_base<_Rp(_ArgTypes...)>
|
||||
{
|
||||
__compressed_pair<_Fp, _Alloc> __f_;
|
||||
@ -1825,7 +1829,7 @@ __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ...
|
||||
template <class _Callable> class __packaged_task_function;
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class __packaged_task_function<_Rp(_ArgTypes...)>
|
||||
class _LIBCPP_AVAILABILITY_FUTURE __packaged_task_function<_Rp(_ArgTypes...)>
|
||||
{
|
||||
typedef __packaged_task_base<_Rp(_ArgTypes...)> __base;
|
||||
typename aligned_storage<3*sizeof(void*)>::type __buf_;
|
||||
@ -2000,7 +2004,7 @@ __packaged_task_function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) cons
|
||||
}
|
||||
|
||||
template<class _Rp, class ..._ArgTypes>
|
||||
class _LIBCPP_TEMPLATE_VIS packaged_task<_Rp(_ArgTypes...)>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<_Rp(_ArgTypes...)>
|
||||
{
|
||||
public:
|
||||
typedef _Rp result_type; // extension
|
||||
@ -2129,7 +2133,7 @@ packaged_task<_Rp(_ArgTypes...)>::reset()
|
||||
}
|
||||
|
||||
template<class ..._ArgTypes>
|
||||
class _LIBCPP_TEMPLATE_VIS packaged_task<void(_ArgTypes...)>
|
||||
class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE packaged_task<void(_ArgTypes...)>
|
||||
{
|
||||
public:
|
||||
typedef void result_type; // extension
|
||||
@ -2517,7 +2521,7 @@ shared_future<_Rp&>::operator=(const shared_future& __rhs)
|
||||
}
|
||||
|
||||
template <>
|
||||
class _LIBCPP_TYPE_VIS shared_future<void>
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future<void>
|
||||
{
|
||||
__assoc_sub_state* __state_;
|
||||
|
||||
|
@ -1675,9 +1675,11 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x)
|
||||
return __is;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<wchar_t>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_iostream<char>)
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -1402,6 +1402,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
||||
this->__format_int(__fmt+1, __len, true, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<long>::digits / 3)
|
||||
+ ((numeric_limits<long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 2;
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
@ -1428,6 +1429,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
||||
this->__format_int(__fmt+1, __len, true, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
|
||||
+ ((numeric_limits<long long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 2;
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
@ -1454,6 +1456,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
||||
this->__format_int(__fmt+1, __len, false, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
|
||||
+ ((numeric_limits<unsigned long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 1;
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
@ -1480,6 +1483,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
|
||||
this->__format_int(__fmt+1, __len, false, __iob.flags());
|
||||
const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
|
||||
+ ((numeric_limits<unsigned long long>::digits % 3) != 0)
|
||||
+ ((__iob.flags() & ios_base::showbase) != 0)
|
||||
+ 1;
|
||||
char __nar[__nbuf];
|
||||
int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
|
||||
@ -1685,6 +1689,22 @@ protected:
|
||||
~__time_get_c_storage() {}
|
||||
};
|
||||
|
||||
template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
|
||||
template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
|
||||
|
||||
template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
|
||||
template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
|
||||
|
||||
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
|
||||
class _LIBCPP_TEMPLATE_VIS time_get
|
||||
: public locale::facet,
|
||||
@ -2825,7 +2845,7 @@ money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// drop through
|
||||
_LIBCPP_FALLTHROUGH();
|
||||
case money_base::none:
|
||||
if (__p != 3)
|
||||
{
|
||||
|
@ -3559,7 +3559,7 @@ template <class _Tp, class _Dp, class _Alloc>
|
||||
const void*
|
||||
__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) const _NOEXCEPT
|
||||
{
|
||||
return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : 0;
|
||||
return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_NO_RTTI
|
||||
@ -5293,7 +5293,8 @@ private:
|
||||
friend _LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*);
|
||||
};
|
||||
|
||||
_LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*);
|
||||
_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
__sp_mut& __get_sp_mut(const void*);
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
@ -5304,6 +5305,7 @@ atomic_is_lock_free(const shared_ptr<_Tp>*)
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
shared_ptr<_Tp>
|
||||
atomic_load(const shared_ptr<_Tp>* __p)
|
||||
{
|
||||
@ -5316,6 +5318,7 @@ atomic_load(const shared_ptr<_Tp>* __p)
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
shared_ptr<_Tp>
|
||||
atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order)
|
||||
{
|
||||
@ -5323,6 +5326,7 @@ atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order)
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
void
|
||||
atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
|
||||
{
|
||||
@ -5334,6 +5338,7 @@ atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
void
|
||||
atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order)
|
||||
{
|
||||
@ -5341,6 +5346,7 @@ atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order)
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
shared_ptr<_Tp>
|
||||
atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
|
||||
{
|
||||
@ -5353,6 +5359,7 @@ atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
shared_ptr<_Tp>
|
||||
atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order)
|
||||
{
|
||||
@ -5360,6 +5367,7 @@ atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
bool
|
||||
atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w)
|
||||
{
|
||||
@ -5381,6 +5389,7 @@ atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, share
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
bool
|
||||
atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w)
|
||||
{
|
||||
@ -5389,6 +5398,7 @@ atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
bool
|
||||
atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
|
||||
shared_ptr<_Tp> __w, memory_order, memory_order)
|
||||
@ -5398,6 +5408,7 @@ atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* _
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
|
||||
bool
|
||||
atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
|
||||
shared_ptr<_Tp> __w, memory_order, memory_order)
|
||||
|
@ -146,9 +146,8 @@ _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec
|
||||
|
||||
#if defined(_LIBCPP_BUILDING_LIBRARY) || (_LIBCPP_STD_VER > 11)
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI bad_array_length
|
||||
: public bad_alloc
|
||||
{
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
bad_array_length : public bad_alloc {
|
||||
public:
|
||||
bad_array_length() _NOEXCEPT;
|
||||
virtual ~bad_array_length() _NOEXCEPT;
|
||||
@ -182,7 +181,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, const std::not
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz) _THROW_BAD_ALLOC;
|
||||
@ -190,7 +189,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, const std::n
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
@ -199,7 +198,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::align_val
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete(void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
#endif
|
||||
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
|
||||
@ -207,7 +206,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::align_v
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operator delete[](void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -238,6 +237,9 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void *__ptr) {
|
||||
|
||||
#ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED
|
||||
_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
_LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH
|
||||
#endif
|
||||
void __throw_bad_array_length()
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
|
@ -1080,8 +1080,10 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x)
|
||||
use_facet<ctype<_CharT> >(__os.getloc()).widen('1'));
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<wchar_t>)
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -3997,16 +3997,30 @@ public:
|
||||
{return !(__x == __y);}
|
||||
};
|
||||
|
||||
#ifndef _LIBCPP_MSVCRT
|
||||
extern "C" double lgamma_r(double, int *);
|
||||
#endif
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY double __libcpp_lgamma(double __d) {
|
||||
#if defined(_LIBCPP_MSVCRT)
|
||||
return lgamma(__d);
|
||||
#else
|
||||
int __sign;
|
||||
return lgamma_r(__d, &__sign);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class _IntType>
|
||||
binomial_distribution<_IntType>::param_type::param_type(result_type __t, double __p)
|
||||
binomial_distribution<_IntType>::param_type::param_type(const result_type __t, const double __p)
|
||||
: __t_(__t), __p_(__p)
|
||||
{
|
||||
if (0 < __p_ && __p_ < 1)
|
||||
{
|
||||
__r0_ = static_cast<result_type>((__t_ + 1) * __p_);
|
||||
__pr_ = _VSTD::exp(_VSTD::lgamma(__t_ + 1.) - _VSTD::lgamma(__r0_ + 1.) -
|
||||
_VSTD::lgamma(__t_ - __r0_ + 1.) + __r0_ * _VSTD::log(__p_) +
|
||||
(__t_ - __r0_) * _VSTD::log(1 - __p_));
|
||||
__pr_ = _VSTD::exp(__libcpp_lgamma(__t_ + 1.) -
|
||||
__libcpp_lgamma(__r0_ + 1.) -
|
||||
__libcpp_lgamma(__t_ - __r0_ + 1.) + __r0_ * _VSTD::log(__p_) +
|
||||
(__t_ - __r0_) * _VSTD::log(1 - __p_));
|
||||
__odds_ratio_ = __p_ / (1 - __p_);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ template <class Mutex>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct _LIBCPP_TYPE_VIS __shared_mutex_base
|
||||
struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base
|
||||
{
|
||||
mutex __mut_;
|
||||
condition_variable __gate1_;
|
||||
@ -173,11 +173,11 @@ struct _LIBCPP_TYPE_VIS __shared_mutex_base
|
||||
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
class _LIBCPP_TYPE_VIS shared_mutex
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
|
||||
{
|
||||
__shared_mutex_base __base;
|
||||
public:
|
||||
shared_mutex() : __base() {}
|
||||
_LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
|
||||
_LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
|
||||
|
||||
shared_mutex(const shared_mutex&) = delete;
|
||||
@ -199,7 +199,7 @@ public:
|
||||
#endif
|
||||
|
||||
|
||||
class _LIBCPP_TYPE_VIS shared_timed_mutex
|
||||
class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
|
||||
{
|
||||
__shared_mutex_base __base;
|
||||
public:
|
||||
|
@ -476,11 +476,13 @@ basic_streambuf<_CharT, _Traits>::overflow(int_type)
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_AVAILABILITY_NO_STREAMS_EXTERN_TEMPLATE
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>)
|
||||
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<char>)
|
||||
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<wchar_t>)
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -108,6 +108,7 @@ protected:
|
||||
#endif
|
||||
|
||||
public:
|
||||
_LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
|
||||
virtual ~type_info();
|
||||
|
||||
#if defined(_LIBCPP_HAS_NONUNIQUE_TYPEINFO)
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT)
|
||||
#include "support/runtime/exception_msvc.ipp"
|
||||
#include "support/runtime/exception_pointer_unimplemented.ipp"
|
||||
#include "support/runtime/exception_pointer_msvc.ipp"
|
||||
#elif defined(_LIBCPPABI_VERSION)
|
||||
#include "support/runtime/exception_libcxxabi.ipp"
|
||||
#include "support/runtime/exception_pointer_cxxabi.ipp"
|
||||
|
@ -513,8 +513,8 @@ bool checked_set(CType* out, ChronoType time) {
|
||||
return true;
|
||||
}
|
||||
|
||||
using TimeSpec = struct ::timespec;
|
||||
using StatT = struct ::stat;
|
||||
using TimeSpec = struct timespec;
|
||||
using StatT = struct stat;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
|
||||
|
@ -68,8 +68,8 @@ T&
|
||||
make(A0 a0)
|
||||
{
|
||||
static typename aligned_storage<sizeof(T)>::type buf;
|
||||
::new (&buf) T(a0);
|
||||
return *reinterpret_cast<T*>(&buf);
|
||||
auto *obj = ::new (&buf) T(a0);
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template <class T, class A0, class A1>
|
||||
@ -88,8 +88,8 @@ T&
|
||||
make(A0 a0, A1 a1, A2 a2)
|
||||
{
|
||||
static typename aligned_storage<sizeof(T)>::type buf;
|
||||
::new (&buf) T(a0, a1, a2);
|
||||
return *reinterpret_cast<T*>(&buf);
|
||||
auto *obj = ::new (&buf) T(a0, a1, a2);
|
||||
return *obj;
|
||||
}
|
||||
|
||||
template <typename T, size_t N>
|
||||
@ -480,8 +480,8 @@ locale::__imp::make_global()
|
||||
{
|
||||
// only one thread can get in here and it only gets in once
|
||||
static aligned_storage<sizeof(locale)>::type buf;
|
||||
::new (&buf) locale(locale::classic());
|
||||
return *reinterpret_cast<locale*>(&buf);
|
||||
auto *obj = ::new (&buf) locale(locale::classic());
|
||||
return *obj;
|
||||
}
|
||||
|
||||
locale&
|
||||
|
@ -120,7 +120,7 @@ __shared_weak_count::lock() _NOEXCEPT
|
||||
object_owners+1))
|
||||
return this;
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
|
||||
@ -128,7 +128,7 @@ __shared_weak_count::lock() _NOEXCEPT
|
||||
const void*
|
||||
__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
|
||||
{
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_NO_RTTI
|
||||
@ -154,7 +154,7 @@ __sp_mut::lock() _NOEXCEPT
|
||||
{
|
||||
auto m = static_cast<__libcpp_mutex_t*>(__lx);
|
||||
unsigned count = 0;
|
||||
while (__libcpp_mutex_trylock(m) != 0)
|
||||
while (!__libcpp_mutex_trylock(m))
|
||||
{
|
||||
if (++count > 16)
|
||||
{
|
||||
|
@ -0,0 +1,94 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(_Out_ void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCopy(_Out_ void*,
|
||||
_In_ const void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrAssign(_Inout_ void*, _In_ const void*);
|
||||
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrCompare(_In_ const void*, _In_ const void*);
|
||||
_CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrToBool(_In_ const void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrSwap(_Inout_ void*,
|
||||
_Inout_ void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrCurrentException(_Out_ void*);
|
||||
[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrRethrow(_In_ const void*);
|
||||
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
|
||||
__ExceptionPtrCopyException(_Inout_ void*, _In_ const void*, _In_ const void*);
|
||||
|
||||
namespace std {
|
||||
|
||||
exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||
exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT {
|
||||
__ExceptionPtrCopy(this, &__other);
|
||||
}
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT {
|
||||
__ExceptionPtrAssign(this, &__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT {
|
||||
exception_ptr dummy;
|
||||
__ExceptionPtrAssign(this, &dummy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); }
|
||||
|
||||
exception_ptr::operator bool() const _NOEXCEPT {
|
||||
return __ExceptionPtrToBool(this);
|
||||
}
|
||||
|
||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
|
||||
return __ExceptionPtrCompare(&__x, &__y);
|
||||
}
|
||||
|
||||
|
||||
void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT {
|
||||
__ExceptionPtrSwap(&rhs, &lhs);
|
||||
}
|
||||
|
||||
exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
|
||||
exception_ptr __ret = nullptr;
|
||||
if (__ptr)
|
||||
__ExceptionPtrCopyException(&__ret, __except, __ptr);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
exception_ptr current_exception() _NOEXCEPT {
|
||||
exception_ptr __ret;
|
||||
__ExceptionPtrCurrentException(&__ret);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
|
||||
|
||||
nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {}
|
||||
|
||||
nested_exception::~nested_exception() _NOEXCEPT {}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void nested_exception::rethrow_nested() const {
|
||||
if (__ptr_ == nullptr)
|
||||
terminate();
|
||||
rethrow_exception(__ptr_);
|
||||
}
|
||||
|
||||
} // namespace std
|
@ -842,6 +842,7 @@ class LLVM_NODISCARD APInt {
|
||||
///
|
||||
/// \returns *this
|
||||
APInt &operator*=(const APInt &RHS);
|
||||
APInt &operator*=(uint64_t RHS);
|
||||
|
||||
/// \brief Addition assignment operator.
|
||||
///
|
||||
@ -2043,6 +2044,16 @@ inline APInt operator-(uint64_t LHS, APInt b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
inline APInt operator*(APInt a, uint64_t RHS) {
|
||||
a *= RHS;
|
||||
return a;
|
||||
}
|
||||
|
||||
inline APInt operator*(uint64_t LHS, APInt b) {
|
||||
b *= LHS;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
namespace APIntOps {
|
||||
|
||||
|
@ -217,7 +217,7 @@ class BitVector {
|
||||
unsigned BitPos = Prev % BITWORD_SIZE;
|
||||
BitWord Copy = Bits[WordPos];
|
||||
// Mask off previous bits.
|
||||
Copy &= ~0UL << BitPos;
|
||||
Copy &= maskTrailingZeros<BitWord>(BitPos);
|
||||
|
||||
if (Copy != 0)
|
||||
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
|
||||
@ -229,7 +229,7 @@ class BitVector {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// find_next_unset - Returns the index of the next usnet bit following the
|
||||
/// find_next_unset - Returns the index of the next unset bit following the
|
||||
/// "Prev" bit. Returns -1 if all remaining bits are set.
|
||||
int find_next_unset(unsigned Prev) const {
|
||||
++Prev;
|
||||
@ -253,7 +253,34 @@ class BitVector {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// clear - Clear all bits.
|
||||
/// find_prev - Returns the index of the first set bit that precedes the
|
||||
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
|
||||
int find_prev(unsigned PriorTo) {
|
||||
if (PriorTo == 0)
|
||||
return -1;
|
||||
|
||||
--PriorTo;
|
||||
|
||||
unsigned WordPos = PriorTo / BITWORD_SIZE;
|
||||
unsigned BitPos = PriorTo % BITWORD_SIZE;
|
||||
BitWord Copy = Bits[WordPos];
|
||||
// Mask off next bits.
|
||||
Copy &= maskTrailingOnes<BitWord>(BitPos + 1);
|
||||
|
||||
if (Copy != 0)
|
||||
return (WordPos + 1) * BITWORD_SIZE - countLeadingZeros(Copy) - 1;
|
||||
|
||||
// Check previous words.
|
||||
for (unsigned i = 1; i <= WordPos; ++i) {
|
||||
unsigned Index = WordPos - i;
|
||||
if (Bits[Index] == 0)
|
||||
continue;
|
||||
return (Index + 1) * BITWORD_SIZE - countLeadingZeros(Bits[Index]) - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// clear - Removes all bits from the bitvector. Does not change capacity.
|
||||
void clear() {
|
||||
Size = 0;
|
||||
}
|
||||
|
@ -278,6 +278,24 @@ class SmallBitVector {
|
||||
return getPointer()->find_next_unset(Prev);
|
||||
}
|
||||
|
||||
/// find_prev - Returns the index of the first set bit that precedes the
|
||||
/// the bit at \p PriorTo. Returns -1 if all previous bits are unset.
|
||||
int find_prev(unsigned PriorTo) const {
|
||||
if (isSmall()) {
|
||||
if (PriorTo == 0)
|
||||
return -1;
|
||||
|
||||
--PriorTo;
|
||||
uintptr_t Bits = getSmallBits();
|
||||
Bits &= maskTrailingOnes<uintptr_t>(PriorTo + 1);
|
||||
if (Bits == 0)
|
||||
return -1;
|
||||
|
||||
return NumBaseBits - countLeadingZeros(Bits) - 1;
|
||||
}
|
||||
return getPointer()->find_prev(PriorTo);
|
||||
}
|
||||
|
||||
/// Clear all bits.
|
||||
void clear() {
|
||||
if (!isSmall())
|
||||
|
@ -220,8 +220,8 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
BI = df_ext_begin(getHeader(), VisitSet),
|
||||
BE = df_ext_end(getHeader(), VisitSet);
|
||||
|
||||
// Keep track of the number of BBs visited.
|
||||
unsigned NumVisited = 0;
|
||||
// Keep track of the BBs visited.
|
||||
SmallPtrSet<BlockT*, 8> VisitedBBs;
|
||||
|
||||
// Check the individual blocks.
|
||||
for ( ; BI != BE; ++BI) {
|
||||
@ -259,10 +259,18 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
assert(BB != &getHeader()->getParent()->front() &&
|
||||
"Loop contains function entry block!");
|
||||
|
||||
NumVisited++;
|
||||
VisitedBBs.insert(BB);
|
||||
}
|
||||
|
||||
assert(NumVisited == getNumBlocks() && "Unreachable block in loop");
|
||||
if (VisitedBBs.size() != getNumBlocks()) {
|
||||
dbgs() << "The following blocks are unreachable in the loop: ";
|
||||
for (auto BB : Blocks) {
|
||||
if (!VisitedBBs.count(BB)) {
|
||||
dbgs() << *BB << "\n";
|
||||
}
|
||||
}
|
||||
assert(false && "Unreachable block in loop");
|
||||
}
|
||||
|
||||
// Check the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
|
@ -54,6 +54,18 @@ class ProfileSummaryInfo {
|
||||
ProfileSummaryInfo(Module &M) : M(M) {}
|
||||
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
|
||||
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
|
||||
|
||||
/// Handle the invalidation of this information.
|
||||
///
|
||||
/// When used as a result of \c ProfileSummaryAnalysis this method will be
|
||||
/// called when the module this was computed for changes. Since profile
|
||||
/// summary is immutable after it is annotated on the module, we return false
|
||||
/// here.
|
||||
bool invalidate(Module &, const PreservedAnalyses &,
|
||||
ModuleAnalysisManager::Invalidator &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns the profile count for \p CallInst.
|
||||
static Optional<uint64_t> getProfileCount(const Instruction *CallInst,
|
||||
BlockFrequencyInfo *BFI);
|
||||
|
@ -782,13 +782,13 @@ class ScalarEvolution {
|
||||
|
||||
/// Set the memoized range for the given SCEV.
|
||||
const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint,
|
||||
const ConstantRange &CR) {
|
||||
ConstantRange &&CR) {
|
||||
DenseMap<const SCEV *, ConstantRange> &Cache =
|
||||
Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges;
|
||||
|
||||
auto Pair = Cache.insert({S, CR});
|
||||
auto Pair = Cache.try_emplace(S, std::move(CR));
|
||||
if (!Pair.second)
|
||||
Pair.first->second = CR;
|
||||
Pair.first->second = std::move(CR);
|
||||
return Pair.first->second;
|
||||
}
|
||||
|
||||
@ -816,6 +816,10 @@ class ScalarEvolution {
|
||||
/// Helper function called from createNodeForPHI.
|
||||
const SCEV *createAddRecFromPHI(PHINode *PN);
|
||||
|
||||
/// A helper function for createAddRecFromPHI to handle simple cases.
|
||||
const SCEV *createSimpleAffineAddRec(PHINode *PN, Value *BEValueV,
|
||||
Value *StartValueV);
|
||||
|
||||
/// Helper function called from createNodeForPHI.
|
||||
const SCEV *createNodeFromSelectLikePHI(PHINode *PN);
|
||||
|
||||
@ -1565,7 +1569,7 @@ class ScalarEvolution {
|
||||
/// delinearization).
|
||||
void findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms,
|
||||
SmallVectorImpl<const SCEV *> &Sizes,
|
||||
const SCEV *ElementSize) const;
|
||||
const SCEV *ElementSize);
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void verify() const;
|
||||
|
@ -1115,6 +1115,9 @@ TLI_DEFINE_STRING_INTERNAL("vsprintf")
|
||||
/// int vsscanf(const char *s, const char *format, va_list arg);
|
||||
TLI_DEFINE_ENUM_INTERNAL(vsscanf)
|
||||
TLI_DEFINE_STRING_INTERNAL("vsscanf")
|
||||
/// size_t wcslen (const wchar_t* wcs);
|
||||
TLI_DEFINE_ENUM_INTERNAL(wcslen)
|
||||
TLI_DEFINE_STRING_INTERNAL("wcslen")
|
||||
/// ssize_t write(int fildes, const void *buf, size_t nbyte);
|
||||
TLI_DEFINE_ENUM_INTERNAL(write)
|
||||
TLI_DEFINE_STRING_INTERNAL("write")
|
||||
|
@ -226,6 +226,7 @@ class AsmPrinter : public MachineFunctionPass {
|
||||
FUNCTION_EXIT = 1,
|
||||
TAIL_CALL = 2,
|
||||
LOG_ARGS_ENTER = 3,
|
||||
CUSTOM_EVENT = 4,
|
||||
};
|
||||
|
||||
// The table will contain these structs that point to the sled, the function
|
||||
@ -242,7 +243,7 @@ class AsmPrinter : public MachineFunctionPass {
|
||||
};
|
||||
|
||||
// All the sleds to be emitted.
|
||||
std::vector<XRayFunctionEntry> Sleds;
|
||||
SmallVector<XRayFunctionEntry, 4> Sleds;
|
||||
|
||||
// Helper function to record a given XRay sled.
|
||||
void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind);
|
||||
|
@ -506,6 +506,7 @@ class FastISel {
|
||||
bool selectCast(const User *I, unsigned Opcode);
|
||||
bool selectExtractValue(const User *I);
|
||||
bool selectInsertValue(const User *I);
|
||||
bool selectXRayCustomEvent(const CallInst *II);
|
||||
|
||||
private:
|
||||
/// \brief Handle PHI nodes in successor blocks.
|
||||
|
@ -249,7 +249,7 @@ class FunctionLoweringInfo {
|
||||
void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits,
|
||||
const KnownBits &Known) {
|
||||
// Only install this information if it tells us something.
|
||||
if (NumSignBits == 1 && Known.Zero == 0 && Known.One == 0)
|
||||
if (NumSignBits == 1 && Known.isUnknown())
|
||||
return;
|
||||
|
||||
LiveOutRegInfo.grow(Reg);
|
||||
|
@ -78,7 +78,7 @@ class IRTranslator : public MachineFunctionPass {
|
||||
/// this function.
|
||||
DenseMap<const AllocaInst *, int> FrameIndices;
|
||||
|
||||
/// Methods for translating form LLVM IR to MachineInstr.
|
||||
/// \name Methods for translating form LLVM IR to MachineInstr.
|
||||
/// \see ::translate for general information on the translate methods.
|
||||
/// @{
|
||||
|
||||
|
@ -45,7 +45,7 @@ class MachineIRBuilder {
|
||||
/// Debug location to be set to any instruction we create.
|
||||
DebugLoc DL;
|
||||
|
||||
/// Fields describing the insertion point.
|
||||
/// \name Fields describing the insertion point.
|
||||
/// @{
|
||||
MachineBasicBlock *MBB;
|
||||
MachineBasicBlock::iterator II;
|
||||
@ -84,7 +84,7 @@ class MachineIRBuilder {
|
||||
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II);
|
||||
/// @}
|
||||
|
||||
/// Setters for the insertion point.
|
||||
/// \name Setters for the insertion point.
|
||||
/// @{
|
||||
/// Set the MachineFunction where to build instructions.
|
||||
void setMF(MachineFunction &);
|
||||
@ -98,7 +98,7 @@ class MachineIRBuilder {
|
||||
void setInstr(MachineInstr &MI);
|
||||
/// @}
|
||||
|
||||
/// Control where instructions we create are recorded (typically for
|
||||
/// \name Control where instructions we create are recorded (typically for
|
||||
/// visiting again later during legalization).
|
||||
/// @{
|
||||
void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr);
|
||||
|
@ -309,7 +309,7 @@ class RegBankSelect : public MachineFunctionPass {
|
||||
Impossible
|
||||
};
|
||||
|
||||
/// Convenient types for a list of insertion points.
|
||||
/// \name Convenient types for a list of insertion points.
|
||||
/// @{
|
||||
typedef SmallVector<std::unique_ptr<InsertPoint>, 2> InsertionPoints;
|
||||
typedef InsertionPoints::iterator insertpt_iterator;
|
||||
@ -341,7 +341,7 @@ class RegBankSelect : public MachineFunctionPass {
|
||||
const TargetRegisterInfo &TRI, Pass &P,
|
||||
RepairingKind Kind = RepairingKind::Insert);
|
||||
|
||||
/// Getters.
|
||||
/// \name Getters.
|
||||
/// @{
|
||||
RepairingKind getKind() const { return Kind; }
|
||||
unsigned getOpIdx() const { return OpIdx; }
|
||||
@ -349,7 +349,7 @@ class RegBankSelect : public MachineFunctionPass {
|
||||
bool hasSplit() { return HasSplit; }
|
||||
/// @}
|
||||
|
||||
/// Overloaded methods to add an insertion point.
|
||||
/// \name Overloaded methods to add an insertion point.
|
||||
/// @{
|
||||
/// Add a MBBInsertionPoint to the list of InsertPoints.
|
||||
void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
|
||||
@ -362,7 +362,7 @@ class RegBankSelect : public MachineFunctionPass {
|
||||
void addInsertPoint(InsertPoint &Point);
|
||||
/// @}
|
||||
|
||||
/// Accessors related to the insertion points.
|
||||
/// \name Accessors related to the insertion points.
|
||||
/// @{
|
||||
insertpt_iterator begin() { return InsertPoints.begin(); }
|
||||
insertpt_iterator end() { return InsertPoints.end(); }
|
||||
@ -561,7 +561,7 @@ class RegBankSelect : public MachineFunctionPass {
|
||||
|
||||
/// Find the best mapping for \p MI from \p PossibleMappings.
|
||||
/// \return a reference on the best mapping in \p PossibleMappings.
|
||||
RegisterBankInfo::InstructionMapping &
|
||||
const RegisterBankInfo::InstructionMapping &
|
||||
findBestMapping(MachineInstr &MI,
|
||||
RegisterBankInfo::InstructionMappings &PossibleMappings,
|
||||
SmallVectorImpl<RepairingPlacement> &RepairPts);
|
||||
|
@ -264,7 +264,7 @@ class RegisterBankInfo {
|
||||
/// Convenient type to represent the alternatives for mapping an
|
||||
/// instruction.
|
||||
/// \todo When we move to TableGen this should be an array ref.
|
||||
typedef SmallVector<InstructionMapping, 4> InstructionMappings;
|
||||
typedef SmallVector<const InstructionMapping *, 4> InstructionMappings;
|
||||
|
||||
/// Helper class used to get/create the virtual registers that will be used
|
||||
/// to replace the MachineOperand when applying a mapping.
|
||||
@ -310,7 +310,7 @@ class RegisterBankInfo {
|
||||
OperandsMapper(MachineInstr &MI, const InstructionMapping &InstrMapping,
|
||||
MachineRegisterInfo &MRI);
|
||||
|
||||
/// Getters.
|
||||
/// \name Getters.
|
||||
/// @{
|
||||
/// The MachineInstr being remapped.
|
||||
MachineInstr &getMI() const { return MI; }
|
||||
@ -378,15 +378,23 @@ class RegisterBankInfo {
|
||||
|
||||
/// Keep dynamically allocated PartialMapping in a separate map.
|
||||
/// This shouldn't be needed when everything gets TableGen'ed.
|
||||
mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>> MapOfPartialMappings;
|
||||
mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>>
|
||||
MapOfPartialMappings;
|
||||
|
||||
/// Keep dynamically allocated ValueMapping in a separate map.
|
||||
/// This shouldn't be needed when everything gets TableGen'ed.
|
||||
mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping> > MapOfValueMappings;
|
||||
mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping>>
|
||||
MapOfValueMappings;
|
||||
|
||||
/// Keep dynamically allocated array of ValueMapping in a separate map.
|
||||
/// This shouldn't be needed when everything gets TableGen'ed.
|
||||
mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>> MapOfOperandsMappings;
|
||||
mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>>
|
||||
MapOfOperandsMappings;
|
||||
|
||||
/// Keep dynamically allocated InstructionMapping in a separate map.
|
||||
/// This shouldn't be needed when everything gets TableGen'ed.
|
||||
mutable DenseMap<unsigned, std::unique_ptr<const InstructionMapping>>
|
||||
MapOfInstructionMappings;
|
||||
|
||||
/// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
|
||||
/// RegisterBank instances.
|
||||
@ -425,14 +433,14 @@ class RegisterBankInfo {
|
||||
/// register, a register class, or a register bank.
|
||||
/// In other words, this method will likely fail to find a mapping for
|
||||
/// any generic opcode that has not been lowered by target specific code.
|
||||
InstructionMapping getInstrMappingImpl(const MachineInstr &MI) const;
|
||||
const InstructionMapping &getInstrMappingImpl(const MachineInstr &MI) const;
|
||||
|
||||
/// Get the uniquely generated PartialMapping for the
|
||||
/// given arguments.
|
||||
const PartialMapping &getPartialMapping(unsigned StartIdx, unsigned Length,
|
||||
const RegisterBank &RegBank) const;
|
||||
|
||||
/// Methods to get a uniquely generated ValueMapping.
|
||||
/// \name Methods to get a uniquely generated ValueMapping.
|
||||
/// @{
|
||||
|
||||
/// The most common ValueMapping consists of a single PartialMapping.
|
||||
@ -445,7 +453,7 @@ class RegisterBankInfo {
|
||||
unsigned NumBreakDowns) const;
|
||||
/// @}
|
||||
|
||||
/// Methods to get a uniquely generated array of ValueMapping.
|
||||
/// \name Methods to get a uniquely generated array of ValueMapping.
|
||||
/// @{
|
||||
|
||||
/// Get the uniquely generated array of ValueMapping for the
|
||||
@ -478,6 +486,33 @@ class RegisterBankInfo {
|
||||
std::initializer_list<const ValueMapping *> OpdsMapping) const;
|
||||
/// @}
|
||||
|
||||
/// \name Methods to get a uniquely generated InstructionMapping.
|
||||
/// @{
|
||||
|
||||
private:
|
||||
/// Method to get a uniquely generated InstructionMapping.
|
||||
const InstructionMapping &
|
||||
getInstructionMappingImpl(bool IsInvalid, unsigned ID = InvalidMappingID,
|
||||
unsigned Cost = 0,
|
||||
const ValueMapping *OperandsMapping = nullptr,
|
||||
unsigned NumOperands = 0) const;
|
||||
|
||||
public:
|
||||
/// Method to get a uniquely generated InstructionMapping.
|
||||
const InstructionMapping &
|
||||
getInstructionMapping(unsigned ID, unsigned Cost,
|
||||
const ValueMapping *OperandsMapping,
|
||||
unsigned NumOperands) const {
|
||||
return getInstructionMappingImpl(/*IsInvalid*/ false, ID, Cost,
|
||||
OperandsMapping, NumOperands);
|
||||
}
|
||||
|
||||
/// Method to get a uniquely generated invalid InstructionMapping.
|
||||
const InstructionMapping &getInvalidInstructionMapping() const {
|
||||
return getInstructionMappingImpl(/*IsInvalid*/ true);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Get the register bank for the \p OpIdx-th operand of \p MI form
|
||||
/// the encoding constraints, if any.
|
||||
///
|
||||
@ -603,7 +638,8 @@ class RegisterBankInfo {
|
||||
///
|
||||
/// \note If returnedVal does not verify MI, this would probably mean
|
||||
/// that the target does not support that instruction.
|
||||
virtual InstructionMapping getInstrMapping(const MachineInstr &MI) const;
|
||||
virtual const InstructionMapping &
|
||||
getInstrMapping(const MachineInstr &MI) const;
|
||||
|
||||
/// Get the alternative mappings for \p MI.
|
||||
/// Alternative in the sense different from getInstrMapping.
|
||||
|
@ -17,9 +17,11 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class Module;
|
||||
class raw_ostream;
|
||||
template <typename T> class SmallVectorImpl;
|
||||
|
||||
/// Print LLVM IR using the MIR serialization format to the given output stream.
|
||||
void printMIR(raw_ostream &OS, const Module &M);
|
||||
@ -28,6 +30,17 @@ void printMIR(raw_ostream &OS, const Module &M);
|
||||
/// output stream.
|
||||
void printMIR(raw_ostream &OS, const MachineFunction &MF);
|
||||
|
||||
/// Determine a possible list of successors of a basic block based on the
|
||||
/// basic block machine operand being used inside the block. This should give
|
||||
/// you the correct list of successor blocks in most cases except for things
|
||||
/// like jump tables where the basic block references can't easily be found.
|
||||
/// The MIRPRinter will skip printing successors if they match the result of
|
||||
/// this funciton and the parser will use this function to construct a list if
|
||||
/// it is missing.
|
||||
void guessSuccessors(const MachineBasicBlock &MBB,
|
||||
SmallVectorImpl<MachineBasicBlock*> &Successors,
|
||||
bool &IsFallthrough);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -520,6 +520,14 @@ class MachineFrameInfo {
|
||||
bool hasTailCall() const { return HasTailCall; }
|
||||
void setHasTailCall() { HasTailCall = true; }
|
||||
|
||||
/// Computes the maximum size of a callframe and the AdjustsStack property.
|
||||
/// This only works for targets defining
|
||||
/// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(),
|
||||
/// and getFrameSize().
|
||||
/// This is usually computed by the prologue epilogue inserter but some
|
||||
/// targets may call this to compute it earlier.
|
||||
void computeMaxCallFrameSize(const MachineFunction &MF);
|
||||
|
||||
/// Return the maximum size of a call frame that must be
|
||||
/// allocated for an outgoing function call. This is only available if
|
||||
/// CallFrameSetup/Destroy pseudo instructions are used by the target, and
|
||||
|
@ -116,7 +116,7 @@ class MachineModuleInfo : public ImmutablePass {
|
||||
|
||||
// TODO: Ideally, what we'd like is to have a switch that allows emitting
|
||||
// synchronous (precise at call-sites only) CFA into .eh_frame. However,
|
||||
// even under this switch, we'd like .debug_frame to be precise when using.
|
||||
// even under this switch, we'd like .debug_frame to be precise when using
|
||||
// -g. At this moment, there's no way to specify that some CFI directives
|
||||
// go into .eh_frame only, while others go into .debug_frame only.
|
||||
|
||||
|
@ -21,7 +21,7 @@ namespace llvm {
|
||||
namespace codeview {
|
||||
class TypeDatabase {
|
||||
public:
|
||||
TypeDatabase() : TypeNameStorage(Allocator) {}
|
||||
explicit TypeDatabase(uint32_t ExpectedSize);
|
||||
|
||||
/// Gets the type index for the next type record.
|
||||
TypeIndex getNextTypeIndex() const;
|
||||
|
@ -310,6 +310,11 @@ class DWARFContextInMemory : public DWARFContext {
|
||||
|
||||
StringRef *MapSectionToMember(StringRef Name);
|
||||
|
||||
/// If Sec is compressed section, decompresses and updates its contents
|
||||
/// provided by Data. Otherwise leaves it unchanged.
|
||||
Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
|
||||
StringRef &Data);
|
||||
|
||||
public:
|
||||
DWARFContextInMemory(const object::ObjectFile &Obj,
|
||||
const LoadedObjectInfo *L = nullptr);
|
||||
|
@ -39,20 +39,18 @@ class DWARFFormValue {
|
||||
|
||||
private:
|
||||
struct ValueType {
|
||||
ValueType() {
|
||||
uval = 0;
|
||||
}
|
||||
ValueType() { uval = 0; }
|
||||
|
||||
union {
|
||||
uint64_t uval;
|
||||
int64_t sval;
|
||||
const char* cstr;
|
||||
const char *cstr;
|
||||
};
|
||||
const uint8_t* data = nullptr;
|
||||
const uint8_t *data = nullptr;
|
||||
};
|
||||
|
||||
dwarf::Form Form; // Form for this value.
|
||||
ValueType Value; // Contains all data for the form.
|
||||
dwarf::Form Form; // Form for this value.
|
||||
ValueType Value; // Contains all data for the form.
|
||||
const DWARFUnit *U = nullptr; // Remember the DWARFUnit at extract time.
|
||||
|
||||
public:
|
||||
@ -84,7 +82,7 @@ class DWARFFormValue {
|
||||
const DWARFUnit *U);
|
||||
|
||||
bool isInlinedCStr() const {
|
||||
return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr;
|
||||
return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;
|
||||
}
|
||||
|
||||
/// getAsFoo functions below return the extracted value as Foo if only
|
||||
@ -135,45 +133,45 @@ class DWARFFormValue {
|
||||
uint8_t AddrSize,
|
||||
llvm::dwarf::DwarfFormat Format);
|
||||
|
||||
/// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
///
|
||||
/// \param debug_info_data the .debug_info data to use to skip the value.
|
||||
/// \param offset_ptr a reference to the offset that will be updated.
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param U the DWARFUnit to use when skipping the form in case the form
|
||||
/// size differs according to data in the DWARFUnit.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
|
||||
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
|
||||
const DWARFUnit *U) const;
|
||||
|
||||
/// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
///
|
||||
/// \param form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param debug_info_data the .debug_info data to use to skip the value.
|
||||
/// \param offset_ptr a reference to the offset that will be updated.
|
||||
/// \param Form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param U the DWARFUnit to use when skipping the form in case the form
|
||||
/// size differs according to data in the DWARFUnit.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
static bool skipValue(dwarf::Form form, DataExtractor debug_info_data,
|
||||
uint32_t *offset_ptr, const DWARFUnit *U);
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr, const DWARFUnit *U);
|
||||
|
||||
/// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
///
|
||||
/// \param form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param debug_info_data the .debug_info data to use to skip the value.
|
||||
/// \param offset_ptr a reference to the offset that will be updated.
|
||||
/// \param Form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param Version DWARF version number.
|
||||
/// \param AddrSize size of an address in bytes.
|
||||
/// \param Format enum value from llvm::dwarf::DwarfFormat.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
static bool skipValue(dwarf::Form form, DataExtractor debug_info_data,
|
||||
uint32_t *offset_ptr, uint16_t Version,
|
||||
uint8_t AddrSize, llvm::dwarf::DwarfFormat Format);
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize,
|
||||
llvm::dwarf::DwarfFormat Format);
|
||||
|
||||
private:
|
||||
void dumpString(raw_ostream &OS) const;
|
||||
@ -181,149 +179,146 @@ class DWARFFormValue {
|
||||
|
||||
namespace dwarf {
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract a string value from it.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and was a string.
|
||||
inline Optional<const char*> toString(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsCString();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract a string value from it.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and was a string.
|
||||
inline Optional<const char *> toString(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsCString();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a string value from it.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the string value or Default if the V doesn't have a value or the
|
||||
/// form value's encoding wasn't a string.
|
||||
inline const char*
|
||||
toString(const Optional<DWARFFormValue>& V, const char *Default) {
|
||||
return toString(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a string value from it.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the string value or Default if the V doesn't have a value or the
|
||||
/// form value's encoding wasn't a string.
|
||||
inline const char *toString(const Optional<DWARFFormValue> &V,
|
||||
const char *Default) {
|
||||
return toString(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract an unsigned constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a unsigned constant form.
|
||||
inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsUnsignedConstant();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract an unsigned constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a unsigned constant form.
|
||||
inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsUnsignedConstant();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a unsigned constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted unsigned value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't an unsigned constant form.
|
||||
inline uint64_t
|
||||
toUnsigned(const Optional<DWARFFormValue>& V, uint64_t Default) {
|
||||
return toUnsigned(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a unsigned constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted unsigned value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't an unsigned constant form.
|
||||
inline uint64_t toUnsigned(const Optional<DWARFFormValue> &V,
|
||||
uint64_t Default) {
|
||||
return toUnsigned(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract an reference.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a reference form.
|
||||
inline Optional<uint64_t> toReference(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsReference();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract an reference.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a reference form.
|
||||
inline Optional<uint64_t> toReference(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsReference();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a reference.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted reference value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't a reference form.
|
||||
inline uint64_t
|
||||
toReference(const Optional<DWARFFormValue>& V, uint64_t Default) {
|
||||
return toReference(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a reference.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted reference value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't a reference form.
|
||||
inline uint64_t toReference(const Optional<DWARFFormValue> &V,
|
||||
uint64_t Default) {
|
||||
return toReference(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract an signed constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a signed constant form.
|
||||
inline Optional<int64_t> toSigned(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsSignedConstant();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract an signed constant.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a signed constant form.
|
||||
inline Optional<int64_t> toSigned(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsSignedConstant();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a signed integer.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted signed integer value or Default if the V doesn't
|
||||
/// have a value or the form value's encoding wasn't a signed integer form.
|
||||
inline int64_t
|
||||
toSigned(const Optional<DWARFFormValue>& V, int64_t Default) {
|
||||
return toSigned(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a signed integer.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted signed integer value or Default if the V doesn't
|
||||
/// have a value or the form value's encoding wasn't a signed integer form.
|
||||
inline int64_t toSigned(const Optional<DWARFFormValue> &V, int64_t Default) {
|
||||
return toSigned(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract an address.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a address form.
|
||||
inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsAddress();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract an address.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a address form.
|
||||
inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsAddress();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a address.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted address value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't an address form.
|
||||
inline uint64_t
|
||||
toAddress(const Optional<DWARFFormValue>& V, uint64_t Default) {
|
||||
return toAddress(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a address.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted address value or Default if the V doesn't have a
|
||||
/// value or the form value's encoding wasn't an address form.
|
||||
inline uint64_t toAddress(const Optional<DWARFFormValue> &V, uint64_t Default) {
|
||||
return toAddress(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract an section offset.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a section offset form.
|
||||
inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsSectionOffset();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract an section offset.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a section offset form.
|
||||
inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsSectionOffset();
|
||||
return None;
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and extract a section offset.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted section offset value or Default if the V doesn't
|
||||
/// have a value or the form value's encoding wasn't a section offset form.
|
||||
inline uint64_t
|
||||
toSectionOffset(const Optional<DWARFFormValue>& V, uint64_t Default) {
|
||||
return toSectionOffset(V).getValueOr(Default);
|
||||
}
|
||||
/// Take an optional DWARFFormValue and extract a section offset.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \param Default the default value to return in case of failure.
|
||||
/// \returns the extracted section offset value or Default if the V doesn't
|
||||
/// have a value or the form value's encoding wasn't a section offset form.
|
||||
inline uint64_t toSectionOffset(const Optional<DWARFFormValue> &V,
|
||||
uint64_t Default) {
|
||||
return toSectionOffset(V).getValueOr(Default);
|
||||
}
|
||||
|
||||
/// Take an optional DWARFFormValue and try to extract block data.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a block form.
|
||||
inline Optional<ArrayRef<uint8_t>>
|
||||
toBlock(const Optional<DWARFFormValue>& V) {
|
||||
if (V)
|
||||
return V->getAsBlock();
|
||||
return None;
|
||||
}
|
||||
/// Take an optional DWARFFormValue and try to extract block data.
|
||||
///
|
||||
/// \param V and optional DWARFFormValue to attempt to extract the value from.
|
||||
/// \returns an optional value that contains a value if the form value
|
||||
/// was valid and has a block form.
|
||||
inline Optional<ArrayRef<uint8_t>> toBlock(const Optional<DWARFFormValue> &V) {
|
||||
if (V)
|
||||
return V->getAsBlock();
|
||||
return None;
|
||||
}
|
||||
|
||||
} // end namespace dwarf
|
||||
|
||||
|
@ -53,14 +53,6 @@ class DbiModuleDescriptor {
|
||||
const ModuleInfoHeader *Layout = nullptr;
|
||||
};
|
||||
|
||||
struct ModuleInfoEx {
|
||||
ModuleInfoEx(const DbiModuleDescriptor &Info) : Info(Info) {}
|
||||
ModuleInfoEx(const ModuleInfoEx &Ex) = default;
|
||||
|
||||
DbiModuleDescriptor Info;
|
||||
std::vector<StringRef> SourceFiles;
|
||||
};
|
||||
|
||||
} // end namespace pdb
|
||||
|
||||
template <> struct VarStreamArrayExtractor<pdb::DbiModuleDescriptor> {
|
||||
|
114
contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
Normal file
114
contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
Normal file
@ -0,0 +1,114 @@
|
||||
//===- DbiModuleList.h - PDB module information list ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
|
||||
#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
|
||||
#include "llvm/Support/BinaryStreamArray.h"
|
||||
#include "llvm/Support/BinaryStreamRef.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class DbiModuleList;
|
||||
struct FileInfoSubstreamHeader;
|
||||
|
||||
class DbiModuleSourceFilesIterator
|
||||
: public iterator_facade_base<DbiModuleSourceFilesIterator,
|
||||
std::random_access_iterator_tag, StringRef> {
|
||||
typedef iterator_facade_base<DbiModuleSourceFilesIterator,
|
||||
std::random_access_iterator_tag, StringRef>
|
||||
BaseType;
|
||||
|
||||
public:
|
||||
DbiModuleSourceFilesIterator(const DbiModuleList &Modules, uint32_t Modi,
|
||||
uint16_t Filei);
|
||||
DbiModuleSourceFilesIterator() = default;
|
||||
DbiModuleSourceFilesIterator &
|
||||
operator=(const DbiModuleSourceFilesIterator &R) = default;
|
||||
|
||||
bool operator==(const DbiModuleSourceFilesIterator &R) const;
|
||||
|
||||
const StringRef &operator*() const { return ThisValue; }
|
||||
StringRef &operator*() { return ThisValue; }
|
||||
|
||||
bool operator<(const DbiModuleSourceFilesIterator &RHS) const;
|
||||
std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const;
|
||||
DbiModuleSourceFilesIterator &operator+=(std::ptrdiff_t N);
|
||||
DbiModuleSourceFilesIterator &operator-=(std::ptrdiff_t N);
|
||||
|
||||
private:
|
||||
void setValue();
|
||||
|
||||
bool isEnd() const;
|
||||
bool isCompatible(const DbiModuleSourceFilesIterator &R) const;
|
||||
bool isUniversalEnd() const;
|
||||
|
||||
StringRef ThisValue;
|
||||
const DbiModuleList *Modules{nullptr};
|
||||
uint32_t Modi{0};
|
||||
uint16_t Filei{0};
|
||||
};
|
||||
|
||||
class DbiModuleList {
|
||||
friend DbiModuleSourceFilesIterator;
|
||||
|
||||
public:
|
||||
Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo);
|
||||
|
||||
Expected<StringRef> getFileName(uint32_t Index) const;
|
||||
uint32_t getModuleCount() const;
|
||||
uint32_t getSourceFileCount() const;
|
||||
uint16_t getSourceFileCount(uint32_t Modi) const;
|
||||
|
||||
iterator_range<DbiModuleSourceFilesIterator>
|
||||
source_files(uint32_t Modi) const;
|
||||
|
||||
DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const;
|
||||
|
||||
private:
|
||||
Error initializeModInfo(BinaryStreamRef ModInfo);
|
||||
Error initializeFileInfo(BinaryStreamRef FileInfo);
|
||||
|
||||
VarStreamArray<DbiModuleDescriptor> Descriptors;
|
||||
|
||||
FixedStreamArray<support::little32_t> FileNameOffsets;
|
||||
FixedStreamArray<support::ulittle16_t> ModFileCountArray;
|
||||
|
||||
// For each module, there are multiple filenames, which can be obtained by
|
||||
// knowing the index of the file. Given the index of the file, one can use
|
||||
// that as an offset into the FileNameOffsets array, which contains the
|
||||
// absolute offset of the file name in NamesBuffer. Thus, for each module
|
||||
// we store the first index in the FileNameOffsets array for this module.
|
||||
// The number of files for the corresponding module is stored in
|
||||
// ModFileCountArray.
|
||||
std::vector<uint32_t> ModuleInitialFileIndex;
|
||||
|
||||
// In order to provide random access into the Descriptors array, we iterate it
|
||||
// once up front to find the offsets of the individual items and store them in
|
||||
// this array.
|
||||
std::vector<uint32_t> ModuleDescriptorOffsets;
|
||||
|
||||
const FileInfoSubstreamHeader *FileInfoHeader = nullptr;
|
||||
|
||||
BinaryStreamRef ModInfoSubstream;
|
||||
BinaryStreamRef FileInfoSubstream;
|
||||
BinaryStreamRef NamesBuffer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LLVM_DEBUGINFO_PDB_RAW_DBIMODULELIST_H
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
||||
@ -68,9 +69,7 @@ class DbiStream {
|
||||
/// not present, returns InvalidStreamIndex.
|
||||
uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
|
||||
|
||||
ArrayRef<ModuleInfoEx> modules() const;
|
||||
|
||||
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
|
||||
const DbiModuleList &modules() const;
|
||||
|
||||
FixedStreamArray<object::coff_section> getSectionHeaders();
|
||||
|
||||
@ -80,27 +79,22 @@ class DbiStream {
|
||||
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
|
||||
|
||||
private:
|
||||
Error initializeModInfoArray();
|
||||
Error initializeSectionContributionData();
|
||||
Error initializeSectionHeadersData();
|
||||
Error initializeSectionMapData();
|
||||
Error initializeFileInfo();
|
||||
Error initializeFpoRecords();
|
||||
|
||||
PDBFile &Pdb;
|
||||
std::unique_ptr<msf::MappedBlockStream> Stream;
|
||||
|
||||
std::vector<ModuleInfoEx> ModuleInfos;
|
||||
PDBStringTable ECNames;
|
||||
|
||||
BinaryStreamRef ModInfoSubstream;
|
||||
BinaryStreamRef SecContrSubstream;
|
||||
BinaryStreamRef SecMapSubstream;
|
||||
BinaryStreamRef FileInfoSubstream;
|
||||
BinaryStreamRef TypeServerMapSubstream;
|
||||
BinaryStreamRef ECSubstream;
|
||||
|
||||
BinaryStreamRef NamesBuffer;
|
||||
DbiModuleList Modules;
|
||||
|
||||
FixedStreamArray<support::ulittle16_t> DbgStreams;
|
||||
|
||||
@ -108,7 +102,6 @@ class DbiStream {
|
||||
FixedStreamArray<SectionContrib> SectionContribs;
|
||||
FixedStreamArray<SectionContrib2> SectionContribs2;
|
||||
FixedStreamArray<SecMapEntry> SectionMap;
|
||||
FixedStreamArray<support::little32_t> FileNameOffsets;
|
||||
|
||||
std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
|
||||
FixedStreamArray<object::coff_section> SectionHeaders;
|
||||
|
@ -18,7 +18,7 @@ namespace pdb {
|
||||
|
||||
class NativeCompilandSymbol : public NativeRawSymbol {
|
||||
public:
|
||||
NativeCompilandSymbol(NativeSession &Session, const ModuleInfoEx &MI);
|
||||
NativeCompilandSymbol(NativeSession &Session, DbiModuleDescriptor MI);
|
||||
PDB_SymType getSymTag() const override;
|
||||
bool isEditAndContinueEnabled() const override;
|
||||
uint32_t getLexicalParentId() const override;
|
||||
@ -26,7 +26,7 @@ class NativeCompilandSymbol : public NativeRawSymbol {
|
||||
std::string getName() const override;
|
||||
|
||||
private:
|
||||
ModuleInfoEx Module;
|
||||
DbiModuleDescriptor Module;
|
||||
};
|
||||
|
||||
} // namespace pdb
|
||||
|
@ -16,13 +16,13 @@
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
|
||||
class DbiModuleList;
|
||||
class NativeSession;
|
||||
|
||||
class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> {
|
||||
public:
|
||||
explicit NativeEnumModules(NativeSession &Session,
|
||||
ArrayRef<ModuleInfoEx> Modules,
|
||||
uint32_t Index = 0);
|
||||
NativeEnumModules(NativeSession &Session, const DbiModuleList &Modules,
|
||||
uint32_t Index = 0);
|
||||
|
||||
uint32_t getChildCount() const override;
|
||||
std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
|
||||
@ -32,7 +32,7 @@ class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> {
|
||||
|
||||
private:
|
||||
NativeSession &Session;
|
||||
ArrayRef<ModuleInfoEx> Modules;
|
||||
const DbiModuleList &Modules;
|
||||
uint32_t Index;
|
||||
};
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ struct ModInfoFlags {
|
||||
};
|
||||
|
||||
/// The header preceeding each entry in the Module Info substream of the DBI
|
||||
/// stream.
|
||||
/// stream. Corresponds to the type MODI in the reference implementation.
|
||||
struct ModuleInfoHeader {
|
||||
/// Currently opened module. This field is a pointer in the reference
|
||||
/// implementation, but that won't work on 64-bit systems, and anyway it
|
||||
@ -243,9 +243,12 @@ struct ModuleInfoHeader {
|
||||
/// Padding so the next field is 4-byte aligned.
|
||||
char Padding1[2];
|
||||
|
||||
/// Array of [0..NumFiles) DBI name buffer offsets. This field is a pointer
|
||||
/// in the reference implementation, but as with `Mod`, we ignore it for now
|
||||
/// since it is unused.
|
||||
/// Array of [0..NumFiles) DBI name buffer offsets. In the reference
|
||||
/// implementation this field is a pointer. But since you can't portably
|
||||
/// serialize a pointer, on 64-bit platforms they copy all the values except
|
||||
/// this one into the 32-bit version of the struct and use that for
|
||||
/// serialization. Regardless, this field is unused, it is only there to
|
||||
/// store a pointer that can be accessed at runtime.
|
||||
support::ulittle32_t FileNameOffs;
|
||||
|
||||
/// Name Index for src file name
|
||||
|
@ -40,12 +40,12 @@ class TpiStream {
|
||||
|
||||
uint32_t TypeIndexBegin() const;
|
||||
uint32_t TypeIndexEnd() const;
|
||||
uint32_t NumTypeRecords() const;
|
||||
uint32_t getNumTypeRecords() const;
|
||||
uint16_t getTypeHashStreamIndex() const;
|
||||
uint16_t getTypeHashStreamAuxIndex() const;
|
||||
|
||||
uint32_t getHashKeySize() const;
|
||||
uint32_t NumHashBuckets() const;
|
||||
uint32_t getNumHashBuckets() const;
|
||||
FixedStreamArray<support::ulittle32_t> getHashValues() const;
|
||||
FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
|
||||
HashTable &getHashAdjusters();
|
||||
@ -55,8 +55,6 @@ class TpiStream {
|
||||
Error commit();
|
||||
|
||||
private:
|
||||
Error verifyHashValues();
|
||||
|
||||
const PDBFile &Pdb;
|
||||
std::unique_ptr<msf::MappedBlockStream> Stream;
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
|
||||
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -97,6 +99,10 @@ class RuntimeDyldChecker {
|
||||
StringRef SectionName,
|
||||
bool LocalAddress);
|
||||
|
||||
/// \brief If there is a section at the given local address, return its load
|
||||
/// address, otherwise return none.
|
||||
Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
|
||||
};
|
||||
|
@ -244,7 +244,8 @@ class AttributeSet {
|
||||
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
|
||||
std::string getAsString(bool InAttrGrp = false) const;
|
||||
|
||||
typedef const Attribute *iterator;
|
||||
using iterator = const Attribute *;
|
||||
|
||||
iterator begin() const;
|
||||
iterator end() const;
|
||||
};
|
||||
@ -479,7 +480,7 @@ class AttributeList {
|
||||
/// \brief Return the attributes at the index as a string.
|
||||
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
|
||||
|
||||
typedef ArrayRef<Attribute>::iterator iterator;
|
||||
using iterator = ArrayRef<Attribute>::iterator;
|
||||
|
||||
iterator begin(unsigned Slot) const;
|
||||
iterator end(unsigned Slot) const;
|
||||
@ -662,11 +663,11 @@ class AttrBuilder {
|
||||
bool empty() const { return Attrs.none(); }
|
||||
|
||||
// Iterators for target-dependent attributes.
|
||||
typedef std::pair<std::string, std::string> td_type;
|
||||
typedef std::map<std::string, std::string>::iterator td_iterator;
|
||||
typedef std::map<std::string, std::string>::const_iterator td_const_iterator;
|
||||
typedef iterator_range<td_iterator> td_range;
|
||||
typedef iterator_range<td_const_iterator> td_const_range;
|
||||
using td_type = std::pair<std::string, std::string>;
|
||||
using td_iterator = std::map<std::string, std::string>::iterator;
|
||||
using td_const_iterator = std::map<std::string, std::string>::const_iterator;
|
||||
using td_range = iterator_range<td_iterator>;
|
||||
using td_const_range = iterator_range<td_const_iterator>;
|
||||
|
||||
td_iterator td_begin() { return TargetDepAttrs.begin(); }
|
||||
td_iterator td_end() { return TargetDepAttrs.end(); }
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/IR/SymbolTableListTraits.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm-c/Types.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
@ -31,7 +32,9 @@ class CallInst;
|
||||
class Function;
|
||||
class LandingPadInst;
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class TerminatorInst;
|
||||
class ValueSymbolTable;
|
||||
|
||||
/// \brief LLVM Basic Block Representation
|
||||
///
|
||||
@ -51,7 +54,7 @@ class TerminatorInst;
|
||||
class BasicBlock : public Value, // Basic blocks are data objects also
|
||||
public ilist_node_with_parent<BasicBlock, Function> {
|
||||
public:
|
||||
typedef SymbolTableList<Instruction> InstListType;
|
||||
using InstListType = SymbolTableList<Instruction>;
|
||||
|
||||
private:
|
||||
friend class BlockAddress;
|
||||
@ -80,10 +83,10 @@ class BasicBlock : public Value, // Basic blocks are data objects also
|
||||
LLVMContext &getContext() const;
|
||||
|
||||
/// Instruction iterators...
|
||||
typedef InstListType::iterator iterator;
|
||||
typedef InstListType::const_iterator const_iterator;
|
||||
typedef InstListType::reverse_iterator reverse_iterator;
|
||||
typedef InstListType::const_reverse_iterator const_reverse_iterator;
|
||||
using iterator = InstListType::iterator;
|
||||
using const_iterator = InstListType::const_iterator;
|
||||
using reverse_iterator = InstListType::reverse_iterator;
|
||||
using const_reverse_iterator = InstListType::const_reverse_iterator;
|
||||
|
||||
/// \brief Creates a new BasicBlock.
|
||||
///
|
||||
|
@ -37,9 +37,9 @@ namespace llvm {
|
||||
template <class Ptr, class USE_iterator> // Predecessor Iterator
|
||||
class PredIterator : public std::iterator<std::forward_iterator_tag,
|
||||
Ptr, ptrdiff_t, Ptr*, Ptr*> {
|
||||
typedef std::iterator<std::forward_iterator_tag, Ptr, ptrdiff_t, Ptr*,
|
||||
Ptr*> super;
|
||||
typedef PredIterator<Ptr, USE_iterator> Self;
|
||||
using super =
|
||||
std::iterator<std::forward_iterator_tag, Ptr, ptrdiff_t, Ptr*, Ptr*>;
|
||||
using Self = PredIterator<Ptr, USE_iterator>;
|
||||
USE_iterator It;
|
||||
|
||||
inline void advancePastNonTerminators() {
|
||||
@ -49,8 +49,8 @@ class PredIterator : public std::iterator<std::forward_iterator_tag,
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename super::pointer pointer;
|
||||
typedef typename super::reference reference;
|
||||
using pointer = typename super::pointer;
|
||||
using reference = typename super::reference;
|
||||
|
||||
PredIterator() = default;
|
||||
explicit inline PredIterator(Ptr *bb) : It(bb->user_begin()) {
|
||||
@ -90,11 +90,11 @@ class PredIterator : public std::iterator<std::forward_iterator_tag,
|
||||
}
|
||||
};
|
||||
|
||||
typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator;
|
||||
typedef PredIterator<const BasicBlock,
|
||||
Value::const_user_iterator> const_pred_iterator;
|
||||
typedef iterator_range<pred_iterator> pred_range;
|
||||
typedef iterator_range<const_pred_iterator> pred_const_range;
|
||||
using pred_iterator = PredIterator<BasicBlock, Value::user_iterator>;
|
||||
using const_pred_iterator =
|
||||
PredIterator<const BasicBlock, Value::const_user_iterator>;
|
||||
using pred_range = iterator_range<pred_iterator>;
|
||||
using pred_const_range = iterator_range<const_pred_iterator>;
|
||||
|
||||
inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); }
|
||||
inline const_pred_iterator pred_begin(const BasicBlock *BB) {
|
||||
@ -118,12 +118,12 @@ inline pred_const_range predecessors(const BasicBlock *BB) {
|
||||
// BasicBlock succ_iterator helpers
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
typedef TerminatorInst::SuccIterator<TerminatorInst *, BasicBlock>
|
||||
succ_iterator;
|
||||
typedef TerminatorInst::SuccIterator<const TerminatorInst *, const BasicBlock>
|
||||
succ_const_iterator;
|
||||
typedef iterator_range<succ_iterator> succ_range;
|
||||
typedef iterator_range<succ_const_iterator> succ_const_range;
|
||||
using succ_iterator =
|
||||
TerminatorInst::SuccIterator<TerminatorInst *, BasicBlock>;
|
||||
using succ_const_iterator =
|
||||
TerminatorInst::SuccIterator<const TerminatorInst *, const BasicBlock>;
|
||||
using succ_range = iterator_range<succ_iterator>;
|
||||
using succ_const_range = iterator_range<succ_const_iterator>;
|
||||
|
||||
inline succ_iterator succ_begin(BasicBlock *BB) {
|
||||
return succ_iterator(BB->getTerminator());
|
||||
@ -160,8 +160,8 @@ struct isPodLike<TerminatorInst::SuccIterator<T, U>> {
|
||||
// graph of basic blocks...
|
||||
|
||||
template <> struct GraphTraits<BasicBlock*> {
|
||||
typedef BasicBlock *NodeRef;
|
||||
typedef succ_iterator ChildIteratorType;
|
||||
using NodeRef = BasicBlock *;
|
||||
using ChildIteratorType = succ_iterator;
|
||||
|
||||
static NodeRef getEntryNode(BasicBlock *BB) { return BB; }
|
||||
static ChildIteratorType child_begin(NodeRef N) { return succ_begin(N); }
|
||||
@ -169,8 +169,8 @@ template <> struct GraphTraits<BasicBlock*> {
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<const BasicBlock*> {
|
||||
typedef const BasicBlock *NodeRef;
|
||||
typedef succ_const_iterator ChildIteratorType;
|
||||
using NodeRef = const BasicBlock *;
|
||||
using ChildIteratorType = succ_const_iterator;
|
||||
|
||||
static NodeRef getEntryNode(const BasicBlock *BB) { return BB; }
|
||||
|
||||
@ -184,16 +184,18 @@ template <> struct GraphTraits<const BasicBlock*> {
|
||||
// instead of the successor edges.
|
||||
//
|
||||
template <> struct GraphTraits<Inverse<BasicBlock*>> {
|
||||
typedef BasicBlock *NodeRef;
|
||||
typedef pred_iterator ChildIteratorType;
|
||||
using NodeRef = BasicBlock *;
|
||||
using ChildIteratorType = pred_iterator;
|
||||
|
||||
static NodeRef getEntryNode(Inverse<BasicBlock *> G) { return G.Graph; }
|
||||
static ChildIteratorType child_begin(NodeRef N) { return pred_begin(N); }
|
||||
static ChildIteratorType child_end(NodeRef N) { return pred_end(N); }
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse<const BasicBlock*>> {
|
||||
typedef const BasicBlock *NodeRef;
|
||||
typedef const_pred_iterator ChildIteratorType;
|
||||
using NodeRef = const BasicBlock *;
|
||||
using ChildIteratorType = const_pred_iterator;
|
||||
|
||||
static NodeRef getEntryNode(Inverse<const BasicBlock *> G) { return G.Graph; }
|
||||
static ChildIteratorType child_begin(NodeRef N) { return pred_begin(N); }
|
||||
static ChildIteratorType child_end(NodeRef N) { return pred_end(N); }
|
||||
@ -211,7 +213,7 @@ template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> {
|
||||
static NodeRef getEntryNode(Function *F) { return &F->getEntryBlock(); }
|
||||
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef pointer_iterator<Function::iterator> nodes_iterator;
|
||||
using nodes_iterator = pointer_iterator<Function::iterator>;
|
||||
|
||||
static nodes_iterator nodes_begin(Function *F) {
|
||||
return nodes_iterator(F->begin());
|
||||
@ -228,7 +230,7 @@ template <> struct GraphTraits<const Function*> :
|
||||
static NodeRef getEntryNode(const Function *F) { return &F->getEntryBlock(); }
|
||||
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef pointer_iterator<Function::const_iterator> nodes_iterator;
|
||||
using nodes_iterator = pointer_iterator<Function::const_iterator>;
|
||||
|
||||
static nodes_iterator nodes_begin(const Function *F) {
|
||||
return nodes_iterator(F->begin());
|
||||
|
@ -207,7 +207,7 @@ class CallSiteBase {
|
||||
|
||||
/// The type of iterator to use when looping over actual arguments at this
|
||||
/// call site.
|
||||
typedef IterTy arg_iterator;
|
||||
using arg_iterator = IterTy;
|
||||
|
||||
iterator_range<IterTy> args() const {
|
||||
return make_range(arg_begin(), arg_end());
|
||||
@ -231,7 +231,7 @@ class CallSiteBase {
|
||||
|
||||
/// Type of iterator to use when looping over data operands at this call site
|
||||
/// (see below).
|
||||
typedef IterTy data_operand_iterator;
|
||||
using data_operand_iterator = IterTy;
|
||||
|
||||
/// data_operands_begin/data_operands_end - Return iterators iterating over
|
||||
/// the call / invoke argument list and bundle operands. For invokes, this is
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- C++ -*-===//
|
||||
//===- llvm/CallingConv.h - LLVM Calling Conventions ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -20,8 +20,9 @@ namespace llvm {
|
||||
/// the well-known calling conventions.
|
||||
///
|
||||
namespace CallingConv {
|
||||
|
||||
/// LLVM IR allows to use arbitrary numbers as calling convention identifiers.
|
||||
typedef unsigned ID;
|
||||
using ID = unsigned;
|
||||
|
||||
/// A set of enums which specify the assigned numeric values for known llvm
|
||||
/// calling conventions.
|
||||
@ -203,8 +204,9 @@ namespace CallingConv {
|
||||
/// The highest possible calling convention ID. Must be some 2^k - 1.
|
||||
MaxID = 1023
|
||||
};
|
||||
} // End CallingConv namespace
|
||||
|
||||
} // End llvm namespace
|
||||
} // end namespace CallingConv
|
||||
|
||||
#endif
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_IR_CALLINGCONV_H
|
||||
|
@ -41,7 +41,7 @@ namespace llvm {
|
||||
class MDNode;
|
||||
|
||||
/// This class represents a range of values.
|
||||
class ConstantRange {
|
||||
class LLVM_NODISCARD ConstantRange {
|
||||
APInt Lower, Upper;
|
||||
|
||||
public:
|
||||
@ -167,7 +167,10 @@ class ConstantRange {
|
||||
APInt getSetSize() const;
|
||||
|
||||
/// Compare set size of this range with the range CR.
|
||||
bool isSizeStrictlySmallerThanOf(const ConstantRange &CR) const;
|
||||
bool isSizeStrictlySmallerThan(const ConstantRange &CR) const;
|
||||
|
||||
// Compare set size of this range with Value.
|
||||
bool isSizeLargerThan(uint64_t MaxSize) const;
|
||||
|
||||
/// Return the largest unsigned value contained in the ConstantRange.
|
||||
APInt getUnsignedMax() const;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===--------- llvm/DataLayout.h - Data size & alignment info ---*- C++ -*-===//
|
||||
//===- llvm/DataLayout.h - Data size & alignment info -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -20,27 +20,32 @@
|
||||
#ifndef LLVM_IR_DATALAYOUT_H
|
||||
#define LLVM_IR_DATALAYOUT_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// This needs to be outside of the namespace, to avoid conflict with llvm-c
|
||||
// decl.
|
||||
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
|
||||
using LLVMTargetDataRef = struct LLVMOpaqueTargetData *;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
class StructType;
|
||||
class StructLayout;
|
||||
class Triple;
|
||||
class GlobalVariable;
|
||||
class LLVMContext;
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
class Module;
|
||||
class StructLayout;
|
||||
class Triple;
|
||||
class Value;
|
||||
|
||||
/// Enum used to categorize the alignment types stored by LayoutAlignElem
|
||||
enum AlignTypeEnum {
|
||||
@ -72,6 +77,7 @@ struct LayoutAlignElem {
|
||||
|
||||
static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width);
|
||||
|
||||
bool operator==(const LayoutAlignElem &rhs) const;
|
||||
};
|
||||
|
||||
@ -90,6 +96,7 @@ struct PointerAlignElem {
|
||||
/// Initializer
|
||||
static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign,
|
||||
unsigned PrefAlign, uint32_t TypeByteWidth);
|
||||
|
||||
bool operator==(const PointerAlignElem &rhs) const;
|
||||
};
|
||||
|
||||
@ -121,7 +128,7 @@ class DataLayout {
|
||||
|
||||
/// \brief Primitive type alignment data. This is sorted by type and bit
|
||||
/// width during construction.
|
||||
typedef SmallVector<LayoutAlignElem, 16> AlignmentsTy;
|
||||
using AlignmentsTy = SmallVector<LayoutAlignElem, 16>;
|
||||
AlignmentsTy Alignments;
|
||||
|
||||
AlignmentsTy::const_iterator
|
||||
@ -136,7 +143,7 @@ class DataLayout {
|
||||
/// \brief The string representation used to create this DataLayout
|
||||
std::string StringRepresentation;
|
||||
|
||||
typedef SmallVector<PointerAlignElem, 8> PointersTy;
|
||||
using PointersTy = SmallVector<PointerAlignElem, 8>;
|
||||
PointersTy Pointers;
|
||||
|
||||
PointersTy::const_iterator
|
||||
@ -147,7 +154,7 @@ class DataLayout {
|
||||
PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace);
|
||||
|
||||
// The StructType -> StructLayout map.
|
||||
mutable void *LayoutMap;
|
||||
mutable void *LayoutMap = nullptr;
|
||||
|
||||
/// Pointers in these address spaces are non-integral, and don't have a
|
||||
/// well-defined bitwise representation.
|
||||
@ -172,16 +179,16 @@ class DataLayout {
|
||||
|
||||
public:
|
||||
/// Constructs a DataLayout from a specification string. See reset().
|
||||
explicit DataLayout(StringRef LayoutDescription) : LayoutMap(nullptr) {
|
||||
explicit DataLayout(StringRef LayoutDescription) {
|
||||
reset(LayoutDescription);
|
||||
}
|
||||
|
||||
/// Initialize target data from properties stored in the module.
|
||||
explicit DataLayout(const Module *M);
|
||||
|
||||
void init(const Module *M);
|
||||
DataLayout(const DataLayout &DL) { *this = DL; }
|
||||
|
||||
DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; }
|
||||
~DataLayout(); // Not virtual, do not subclass this class
|
||||
|
||||
DataLayout &operator=(const DataLayout &DL) {
|
||||
clear();
|
||||
@ -200,7 +207,7 @@ class DataLayout {
|
||||
bool operator==(const DataLayout &Other) const;
|
||||
bool operator!=(const DataLayout &Other) const { return !(*this == Other); }
|
||||
|
||||
~DataLayout(); // Not virtual, do not subclass this class
|
||||
void init(const Module *M);
|
||||
|
||||
/// Parse a data layout string (with fallback to default values).
|
||||
void reset(StringRef LayoutDescription);
|
||||
@ -489,6 +496,7 @@ class StructLayout {
|
||||
unsigned IsPadded : 1;
|
||||
unsigned NumElements : 31;
|
||||
uint64_t MemberOffsets[1]; // variable sized array!
|
||||
|
||||
public:
|
||||
uint64_t getSizeInBytes() const { return StructSize; }
|
||||
|
||||
@ -515,6 +523,7 @@ class StructLayout {
|
||||
|
||||
private:
|
||||
friend class DataLayout; // Only DataLayout can create this class
|
||||
|
||||
StructLayout(StructType *ST, const DataLayout &DL);
|
||||
};
|
||||
|
||||
@ -560,6 +569,6 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
|
||||
}
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_IR_DATALAYOUT_H
|
||||
|
@ -21,17 +21,12 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
|
||||
class DbgDeclareInst;
|
||||
class DbgValueInst;
|
||||
template <typename K, typename V, typename KeyInfoT, typename BucketT>
|
||||
class DenseMap;
|
||||
class Module;
|
||||
|
||||
/// \brief Find subprogram that is enclosing this scope.
|
||||
DISubprogram *getDISubprogram(const MDNode *Scope);
|
||||
@ -95,13 +90,13 @@ class DebugInfoFinder {
|
||||
bool addScope(DIScope *Scope);
|
||||
|
||||
public:
|
||||
typedef SmallVectorImpl<DICompileUnit *>::const_iterator
|
||||
compile_unit_iterator;
|
||||
typedef SmallVectorImpl<DISubprogram *>::const_iterator subprogram_iterator;
|
||||
typedef SmallVectorImpl<DIGlobalVariableExpression *>::const_iterator
|
||||
global_variable_expression_iterator;
|
||||
typedef SmallVectorImpl<DIType *>::const_iterator type_iterator;
|
||||
typedef SmallVectorImpl<DIScope *>::const_iterator scope_iterator;
|
||||
using compile_unit_iterator =
|
||||
SmallVectorImpl<DICompileUnit *>::const_iterator;
|
||||
using subprogram_iterator = SmallVectorImpl<DISubprogram *>::const_iterator;
|
||||
using global_variable_expression_iterator =
|
||||
SmallVectorImpl<DIGlobalVariableExpression *>::const_iterator;
|
||||
using type_iterator = SmallVectorImpl<DIType *>::const_iterator;
|
||||
using scope_iterator = SmallVectorImpl<DIScope *>::const_iterator;
|
||||
|
||||
iterator_range<compile_unit_iterator> compile_units() const {
|
||||
return make_range(CUs.begin(), CUs.end());
|
||||
@ -140,4 +135,4 @@ class DebugInfoFinder {
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_IR_DEBUGINFO_H
|
||||
|
@ -42,7 +42,7 @@ extern template void Calculate<Function, Inverse<BasicBlock *>>(
|
||||
DominatorTreeBaseByGraphTraits<GraphTraits<Inverse<BasicBlock *>>> &DT,
|
||||
Function &F);
|
||||
|
||||
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
|
||||
using DomTreeNode = DomTreeNodeBase<BasicBlock>;
|
||||
|
||||
class BasicBlockEdge {
|
||||
const BasicBlock *Start;
|
||||
@ -70,7 +70,7 @@ class BasicBlockEdge {
|
||||
};
|
||||
|
||||
template <> struct DenseMapInfo<BasicBlockEdge> {
|
||||
typedef DenseMapInfo<const BasicBlock *> BBInfo;
|
||||
using BBInfo = DenseMapInfo<const BasicBlock *>;
|
||||
|
||||
static unsigned getHashValue(const BasicBlockEdge *V);
|
||||
|
||||
@ -113,7 +113,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> {
|
||||
/// preceding statements; this is stated only to assist human understanding.
|
||||
class DominatorTree : public DominatorTreeBase<BasicBlock> {
|
||||
public:
|
||||
typedef DominatorTreeBase<BasicBlock> Base;
|
||||
using Base = DominatorTreeBase<BasicBlock>;
|
||||
|
||||
DominatorTree() : DominatorTreeBase<BasicBlock>(false) {}
|
||||
explicit DominatorTree(Function &F) : DominatorTreeBase<BasicBlock>(false) {
|
||||
@ -168,9 +168,9 @@ class DominatorTree : public DominatorTreeBase<BasicBlock> {
|
||||
// iterable by generic graph iterators.
|
||||
|
||||
template <class Node, class ChildIterator> struct DomTreeGraphTraitsBase {
|
||||
typedef Node *NodeRef;
|
||||
typedef ChildIterator ChildIteratorType;
|
||||
typedef df_iterator<Node *, df_iterator_default_set<Node*>> nodes_iterator;
|
||||
using NodeRef = Node *;
|
||||
using ChildIteratorType = ChildIterator;
|
||||
using nodes_iterator = df_iterator<Node *, df_iterator_default_set<Node*>>;
|
||||
|
||||
static NodeRef getEntryNode(NodeRef N) { return N; }
|
||||
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
|
||||
@ -212,7 +212,7 @@ class DominatorTreeAnalysis : public AnalysisInfoMixin<DominatorTreeAnalysis> {
|
||||
|
||||
public:
|
||||
/// \brief Provide the result typedef for this analysis pass.
|
||||
typedef DominatorTree Result;
|
||||
using Result = DominatorTree;
|
||||
|
||||
/// \brief Run the analysis pass over a function and produce a dominator tree.
|
||||
DominatorTree run(Function &F, FunctionAnalysisManager &);
|
||||
|
@ -466,7 +466,6 @@ class Function : public GlobalObject, public ilist_node<Function> {
|
||||
|
||||
/// @brief Determine if the parameter or return value is marked with NoAlias
|
||||
/// attribute.
|
||||
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
|
||||
bool returnDoesNotAlias() const {
|
||||
return AttributeSets.hasAttribute(AttributeList::ReturnIndex,
|
||||
Attribute::NoAlias);
|
||||
|
@ -95,7 +95,7 @@ class InlineAsm : public Value {
|
||||
isClobber // '~x'
|
||||
};
|
||||
|
||||
typedef std::vector<std::string> ConstraintCodeVector;
|
||||
using ConstraintCodeVector = std::vector<std::string>;
|
||||
|
||||
struct SubConstraintInfo {
|
||||
/// MatchingInput - If this is not -1, this is an output constraint where an
|
||||
@ -112,9 +112,9 @@ class InlineAsm : public Value {
|
||||
SubConstraintInfo() = default;
|
||||
};
|
||||
|
||||
typedef std::vector<SubConstraintInfo> SubConstraintInfoVector;
|
||||
using SubConstraintInfoVector = std::vector<SubConstraintInfo>;
|
||||
struct ConstraintInfo;
|
||||
typedef std::vector<ConstraintInfo> ConstraintInfoVector;
|
||||
using ConstraintInfoVector = std::vector<ConstraintInfo>;
|
||||
|
||||
struct ConstraintInfo {
|
||||
/// Type - The basic type of the constraint: input/output/clobber
|
||||
|
@ -31,20 +31,20 @@ namespace llvm {
|
||||
// inst_iterator and const_inst_iterator's.
|
||||
//
|
||||
template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator {
|
||||
typedef BB_t BBty;
|
||||
typedef BB_i_t BBIty;
|
||||
typedef BI_t BIty;
|
||||
typedef II_t IIty;
|
||||
using BBty = BB_t;
|
||||
using BBIty = BB_i_t;
|
||||
using BIty = BI_t;
|
||||
using IIty = II_t;
|
||||
BB_t *BBs; // BasicBlocksType
|
||||
BB_i_t BB; // BasicBlocksType::iterator
|
||||
BI_t BI; // BasicBlock::iterator
|
||||
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef IIty value_type;
|
||||
typedef signed difference_type;
|
||||
typedef IIty* pointer;
|
||||
typedef IIty& reference;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = IIty;
|
||||
using difference_type = signed;
|
||||
using pointer = IIty *;
|
||||
using reference = IIty &;
|
||||
|
||||
// Default constructor
|
||||
InstIterator() = default;
|
||||
@ -119,13 +119,15 @@ template <class BB_t, class BB_i_t, class BI_t, class II_t> class InstIterator {
|
||||
}
|
||||
};
|
||||
|
||||
typedef InstIterator<SymbolTableList<BasicBlock>, Function::iterator,
|
||||
BasicBlock::iterator, Instruction> inst_iterator;
|
||||
typedef InstIterator<const SymbolTableList<BasicBlock>,
|
||||
Function::const_iterator, BasicBlock::const_iterator,
|
||||
const Instruction> const_inst_iterator;
|
||||
typedef iterator_range<inst_iterator> inst_range;
|
||||
typedef iterator_range<const_inst_iterator> const_inst_range;
|
||||
using inst_iterator =
|
||||
InstIterator<SymbolTableList<BasicBlock>, Function::iterator,
|
||||
BasicBlock::iterator, Instruction>;
|
||||
using const_inst_iterator =
|
||||
InstIterator<const SymbolTableList<BasicBlock>,
|
||||
Function::const_iterator, BasicBlock::const_iterator,
|
||||
const Instruction>;
|
||||
using inst_range = iterator_range<inst_iterator>;
|
||||
using const_inst_range = iterator_range<const_inst_iterator>;
|
||||
|
||||
inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); }
|
||||
inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); }
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- llvm/InstrTypes.h - Important Instruction subclasses ----*- C++ -*-===//
|
||||
//===- llvm/InstrTypes.h - Important Instruction subclasses -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -29,7 +29,9 @@
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/OperandTraits.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/User.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <algorithm>
|
||||
@ -114,17 +116,17 @@ class TerminatorInst : public Instruction {
|
||||
template <class Term, class BB> // Successor Iterator
|
||||
class SuccIterator : public std::iterator<std::random_access_iterator_tag, BB,
|
||||
int, BB *, BB *> {
|
||||
typedef std::iterator<std::random_access_iterator_tag, BB, int, BB *, BB *>
|
||||
super;
|
||||
using super =
|
||||
std::iterator<std::random_access_iterator_tag, BB, int, BB *, BB *>;
|
||||
|
||||
public:
|
||||
typedef typename super::pointer pointer;
|
||||
typedef typename super::reference reference;
|
||||
using pointer = typename super::pointer;
|
||||
using reference = typename super::reference;
|
||||
|
||||
private:
|
||||
Term TermInst;
|
||||
unsigned idx;
|
||||
typedef SuccIterator<Term, BB> Self;
|
||||
using Self = SuccIterator<Term, BB>;
|
||||
|
||||
inline bool index_is_valid(unsigned idx) {
|
||||
return idx < TermInst->getNumSuccessors();
|
||||
@ -260,11 +262,11 @@ class TerminatorInst : public Instruction {
|
||||
}
|
||||
};
|
||||
|
||||
typedef SuccIterator<TerminatorInst *, BasicBlock> succ_iterator;
|
||||
typedef SuccIterator<const TerminatorInst *, const BasicBlock>
|
||||
succ_const_iterator;
|
||||
typedef iterator_range<succ_iterator> succ_range;
|
||||
typedef iterator_range<succ_const_iterator> succ_const_range;
|
||||
using succ_iterator = SuccIterator<TerminatorInst *, BasicBlock>;
|
||||
using succ_const_iterator =
|
||||
SuccIterator<const TerminatorInst *, const BasicBlock>;
|
||||
using succ_range = iterator_range<succ_iterator>;
|
||||
using succ_const_range = iterator_range<succ_const_iterator>;
|
||||
|
||||
private:
|
||||
inline succ_iterator succ_begin() { return succ_iterator(this); }
|
||||
@ -341,14 +343,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
|
||||
|
||||
class BinaryOperator : public Instruction {
|
||||
protected:
|
||||
void init(BinaryOps iType);
|
||||
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty,
|
||||
const Twine &Name, Instruction *InsertBefore);
|
||||
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty,
|
||||
const Twine &Name, BasicBlock *InsertAtEnd);
|
||||
|
||||
void init(BinaryOps iType);
|
||||
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
|
||||
BinaryOperator *cloneImpl() const;
|
||||
|
||||
public:
|
||||
@ -1125,8 +1129,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value)
|
||||
//===----------------------------------------------------------------------===//
|
||||
class FuncletPadInst : public Instruction {
|
||||
private:
|
||||
void init(Value *ParentPad, ArrayRef<Value *> Args, const Twine &NameStr);
|
||||
|
||||
FuncletPadInst(const FuncletPadInst &CPI);
|
||||
|
||||
explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
|
||||
@ -1136,11 +1138,14 @@ class FuncletPadInst : public Instruction {
|
||||
ArrayRef<Value *> Args, unsigned Values,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd);
|
||||
|
||||
void init(Value *ParentPad, ArrayRef<Value *> Args, const Twine &NameStr);
|
||||
|
||||
protected:
|
||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||
friend class Instruction;
|
||||
friend class CatchPadInst;
|
||||
friend class CleanupPadInst;
|
||||
|
||||
FuncletPadInst *cloneImpl() const;
|
||||
|
||||
public:
|
||||
@ -1261,7 +1266,8 @@ template <typename InputTy> class OperandBundleDefT {
|
||||
|
||||
ArrayRef<InputTy> inputs() const { return Inputs; }
|
||||
|
||||
typedef typename std::vector<InputTy>::const_iterator input_iterator;
|
||||
using input_iterator = typename std::vector<InputTy>::const_iterator;
|
||||
|
||||
size_t input_size() const { return Inputs.size(); }
|
||||
input_iterator input_begin() const { return Inputs.begin(); }
|
||||
input_iterator input_end() const { return Inputs.end(); }
|
||||
@ -1269,8 +1275,8 @@ template <typename InputTy> class OperandBundleDefT {
|
||||
StringRef getTag() const { return Tag; }
|
||||
};
|
||||
|
||||
typedef OperandBundleDefT<Value *> OperandBundleDef;
|
||||
typedef OperandBundleDefT<const Value *> ConstOperandBundleDef;
|
||||
using OperandBundleDef = OperandBundleDefT<Value *>;
|
||||
using ConstOperandBundleDef = OperandBundleDefT<const Value *>;
|
||||
|
||||
/// \brief A mixin to add operand bundle functionality to llvm instruction
|
||||
/// classes.
|
||||
@ -1553,8 +1559,8 @@ template <typename InstrTy, typename OpIteratorTy> class OperandBundleUser {
|
||||
return OperandBundleUse(BOI.Tag, Inputs);
|
||||
}
|
||||
|
||||
typedef BundleOpInfo *bundle_op_iterator;
|
||||
typedef const BundleOpInfo *const_bundle_op_iterator;
|
||||
using bundle_op_iterator = BundleOpInfo *;
|
||||
using const_bundle_op_iterator = const BundleOpInfo *;
|
||||
|
||||
/// \brief Return the start of the list of BundleOpInfo instances associated
|
||||
/// with this OperandBundleUser.
|
||||
@ -1654,6 +1660,6 @@ template <typename InstrTy, typename OpIteratorTy> class OperandBundleUser {
|
||||
}
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_IR_INSTRTYPES_H
|
||||
|
@ -795,6 +795,14 @@ def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty],
|
||||
def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty],
|
||||
[IntrReadMem, IntrArgMemOnly]>;
|
||||
|
||||
// Xray intrinsics
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Custom event logging for x-ray.
|
||||
// Takes a pointer to a string and the length of the string.
|
||||
def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>, ReadOnly<0>, IntrWriteMem]>;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===------ Memory intrinsics with element-wise atomicity guarantees ------===//
|
||||
//
|
||||
|
||||
|
@ -22,12 +22,26 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.".
|
||||
// and return value are essentially chains, used to force ordering during ISel.
|
||||
def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
// 16-bit multiplications
|
||||
def int_arm_smulbb : GCCBuiltin<"__builtin_arm_smulbb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smulbt : GCCBuiltin<"__builtin_arm_smulbt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smultb : GCCBuiltin<"__builtin_arm_smultb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smultt : GCCBuiltin<"__builtin_arm_smultt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smulwb : GCCBuiltin<"__builtin_arm_smulwb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smulwt : GCCBuiltin<"__builtin_arm_smulwt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Saturating Arithmetic
|
||||
|
||||
def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem, Commutative]>;
|
||||
[Commutative, IntrNoMem]>;
|
||||
def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">,
|
||||
@ -35,6 +49,176 @@ def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">,
|
||||
def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
// Accumulating multiplications
|
||||
def int_arm_smlabb : GCCBuiltin<"__builtin_arm_smlabb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlabt : GCCBuiltin<"__builtin_arm_smlabt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlatb : GCCBuiltin<"__builtin_arm_smlatb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlatt : GCCBuiltin<"__builtin_arm_smlatt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlawb : GCCBuiltin<"__builtin_arm_smlawb">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlawt : GCCBuiltin<"__builtin_arm_smlawt">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
|
||||
// Parallel 16-bit saturation
|
||||
def int_arm_ssat16 : GCCBuiltin<"__builtin_arm_ssat16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_usat16 : GCCBuiltin<"__builtin_arm_usat16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
// Packing and unpacking
|
||||
def int_arm_sxtab16 : GCCBuiltin<"__builtin_arm_sxtab16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_sxtb16 : GCCBuiltin<"__builtin_arm_sxtb16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uxtab16 : GCCBuiltin<"__builtin_arm_uxtab16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uxtb16 : GCCBuiltin<"__builtin_arm_uxtb16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
// Parallel selection, reads the GE flags.
|
||||
def int_arm_sel : GCCBuiltin<"__builtin_arm_sel">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadMem]>;
|
||||
|
||||
// Parallel 8-bit addition and subtraction
|
||||
def int_arm_qadd8 : GCCBuiltin<"__builtin_arm_qadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_qsub8 : GCCBuiltin<"__builtin_arm_qsub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_sadd8 : GCCBuiltin<"__builtin_arm_sadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_shadd8 : GCCBuiltin<"__builtin_arm_shadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_shsub8 : GCCBuiltin<"__builtin_arm_shsub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_ssub8 : GCCBuiltin<"__builtin_arm_ssub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_uadd8 : GCCBuiltin<"__builtin_arm_uadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_uhadd8 : GCCBuiltin<"__builtin_arm_uhadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uhsub8 : GCCBuiltin<"__builtin_arm_uhsub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqadd8 : GCCBuiltin<"__builtin_arm_uqadd8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqsub8 : GCCBuiltin<"__builtin_arm_uqsub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_usub8 : GCCBuiltin<"__builtin_arm_usub8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
// Sum of 8-bit absolute differences
|
||||
def int_arm_usad8 : GCCBuiltin<"__builtin_arm_usad8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_usada8 : GCCBuiltin<"__builtin_arm_usada8">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
|
||||
// Parallel 16-bit addition and subtraction
|
||||
def int_arm_qadd16 : GCCBuiltin<"__builtin_arm_qadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_qasx : GCCBuiltin<"__builtin_arm_qasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_qsax : GCCBuiltin<"__builtin_arm_qsax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_qsub16 : GCCBuiltin<"__builtin_arm_qsub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_sadd16 : GCCBuiltin<"__builtin_arm_sadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_sasx : GCCBuiltin<"__builtin_arm_sasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_shadd16 : GCCBuiltin<"__builtin_arm_shadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_shasx : GCCBuiltin<"__builtin_arm_shasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_shsax : GCCBuiltin<"__builtin_arm_shsax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_shsub16 : GCCBuiltin<"__builtin_arm_shsub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_ssax : GCCBuiltin<"__builtin_arm_ssax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_ssub16 : GCCBuiltin<"__builtin_arm_ssub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_uadd16 : GCCBuiltin<"__builtin_arm_uadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_uasx : GCCBuiltin<"__builtin_arm_uasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
def int_arm_uhadd16 : GCCBuiltin<"__builtin_arm_uhadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uhasx : GCCBuiltin<"__builtin_arm_uhasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uhsax : GCCBuiltin<"__builtin_arm_uhsax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uhsub16 : GCCBuiltin<"__builtin_arm_uhsub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqadd16 : GCCBuiltin<"__builtin_arm_uqadd16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqasx : GCCBuiltin<"__builtin_arm_uqasx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqsax : GCCBuiltin<"__builtin_arm_uqsax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_uqsub16 : GCCBuiltin<"__builtin_arm_uqsub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_usax : GCCBuiltin<"__builtin_arm_usax">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
// Writes to the GE bits.
|
||||
def int_arm_usub16 : GCCBuiltin<"__builtin_arm_usub16">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
|
||||
|
||||
// Parallel 16-bit multiplication
|
||||
def int_arm_smlad : GCCBuiltin<"__builtin_arm_smlad">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smladx : GCCBuiltin<"__builtin_arm_smladx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlald : GCCBuiltin<"__builtin_arm_smlald">,
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlaldx : GCCBuiltin<"__builtin_arm_smlaldx">,
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlsd : GCCBuiltin<"__builtin_arm_smlsd">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlsdx : GCCBuiltin<"__builtin_arm_smlsdx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlsld : GCCBuiltin<"__builtin_arm_smlsld">,
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smlsldx : GCCBuiltin<"__builtin_arm_smlsldx">,
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i64_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_arm_smuad : GCCBuiltin<"__builtin_arm_smuad">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smuadx : GCCBuiltin<"__builtin_arm_smuadx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smusd : GCCBuiltin<"__builtin_arm_smusd">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_arm_smusdx : GCCBuiltin<"__builtin_arm_smusdx">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Load, Store and Clear exclusive
|
||||
|
||||
|
@ -45,58 +45,54 @@ struct CalleeInfo {
|
||||
}
|
||||
};
|
||||
|
||||
/// Struct to hold value either by GUID or GlobalValue*. Values in combined
|
||||
/// indexes as well as indirect calls are GUIDs, all others are GlobalValues.
|
||||
class GlobalValueSummary;
|
||||
|
||||
typedef std::vector<std::unique_ptr<GlobalValueSummary>> GlobalValueSummaryList;
|
||||
|
||||
struct GlobalValueSummaryInfo {
|
||||
/// The GlobalValue corresponding to this summary. This is only used in
|
||||
/// per-module summaries.
|
||||
const GlobalValue *GV = nullptr;
|
||||
|
||||
/// List of global value summary structures for a particular value held
|
||||
/// in the GlobalValueMap. Requires a vector in the case of multiple
|
||||
/// COMDAT values of the same name.
|
||||
GlobalValueSummaryList SummaryList;
|
||||
};
|
||||
|
||||
/// Map from global value GUID to corresponding summary structures. Use a
|
||||
/// std::map rather than a DenseMap so that pointers to the map's value_type
|
||||
/// (which are used by ValueInfo) are not invalidated by insertion. Also it will
|
||||
/// likely incur less overhead, as the value type is not very small and the size
|
||||
/// of the map is unknown, resulting in inefficiencies due to repeated
|
||||
/// insertions and resizing.
|
||||
typedef std::map<GlobalValue::GUID, GlobalValueSummaryInfo>
|
||||
GlobalValueSummaryMapTy;
|
||||
|
||||
/// Struct that holds a reference to a particular GUID in a global value
|
||||
/// summary.
|
||||
struct ValueInfo {
|
||||
/// The value representation used in this instance.
|
||||
enum ValueInfoKind {
|
||||
VI_GUID,
|
||||
VI_Value,
|
||||
};
|
||||
const GlobalValueSummaryMapTy::value_type *Ref = nullptr;
|
||||
ValueInfo() = default;
|
||||
ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {}
|
||||
operator bool() const { return Ref; }
|
||||
|
||||
/// Union of the two possible value types.
|
||||
union ValueUnion {
|
||||
GlobalValue::GUID Id;
|
||||
const GlobalValue *GV;
|
||||
ValueUnion(GlobalValue::GUID Id) : Id(Id) {}
|
||||
ValueUnion(const GlobalValue *GV) : GV(GV) {}
|
||||
};
|
||||
|
||||
/// The value being represented.
|
||||
ValueUnion TheValue;
|
||||
/// The value representation.
|
||||
ValueInfoKind Kind;
|
||||
/// Constructor for a GUID value
|
||||
ValueInfo(GlobalValue::GUID Id = 0) : TheValue(Id), Kind(VI_GUID) {}
|
||||
/// Constructor for a GlobalValue* value
|
||||
ValueInfo(const GlobalValue *V) : TheValue(V), Kind(VI_Value) {}
|
||||
/// Accessor for GUID value
|
||||
GlobalValue::GUID getGUID() const {
|
||||
assert(Kind == VI_GUID && "Not a GUID type");
|
||||
return TheValue.Id;
|
||||
GlobalValue::GUID getGUID() const { return Ref->first; }
|
||||
const GlobalValue *getValue() const { return Ref->second.GV; }
|
||||
ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const {
|
||||
return Ref->second.SummaryList;
|
||||
}
|
||||
/// Accessor for GlobalValue* value
|
||||
const GlobalValue *getValue() const {
|
||||
assert(Kind == VI_Value && "Not a Value type");
|
||||
return TheValue.GV;
|
||||
}
|
||||
bool isGUID() const { return Kind == VI_GUID; }
|
||||
};
|
||||
|
||||
template <> struct DenseMapInfo<ValueInfo> {
|
||||
static inline ValueInfo getEmptyKey() { return ValueInfo((GlobalValue *)-1); }
|
||||
static inline ValueInfo getEmptyKey() {
|
||||
return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1);
|
||||
}
|
||||
static inline ValueInfo getTombstoneKey() {
|
||||
return ValueInfo((GlobalValue *)-2);
|
||||
}
|
||||
static bool isEqual(ValueInfo L, ValueInfo R) {
|
||||
if (L.isGUID() != R.isGUID())
|
||||
return false;
|
||||
return L.isGUID() ? (L.getGUID() == R.getGUID())
|
||||
: (L.getValue() == R.getValue());
|
||||
}
|
||||
static unsigned getHashValue(ValueInfo I) {
|
||||
return I.isGUID() ? I.getGUID() : (uintptr_t)I.getValue();
|
||||
return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2);
|
||||
}
|
||||
static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; }
|
||||
static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; }
|
||||
};
|
||||
|
||||
/// \brief Function and variable summary information to aid decisions and
|
||||
@ -483,19 +479,6 @@ struct TypeIdSummary {
|
||||
/// 160 bits SHA1
|
||||
typedef std::array<uint32_t, 5> ModuleHash;
|
||||
|
||||
/// List of global value summary structures for a particular value held
|
||||
/// in the GlobalValueMap. Requires a vector in the case of multiple
|
||||
/// COMDAT values of the same name.
|
||||
typedef std::vector<std::unique_ptr<GlobalValueSummary>> GlobalValueSummaryList;
|
||||
|
||||
/// Map from global value GUID to corresponding summary structures.
|
||||
/// Use a std::map rather than a DenseMap since it will likely incur
|
||||
/// less overhead, as the value type is not very small and the size
|
||||
/// of the map is unknown, resulting in inefficiencies due to repeated
|
||||
/// insertions and resizing.
|
||||
typedef std::map<GlobalValue::GUID, GlobalValueSummaryList>
|
||||
GlobalValueSummaryMapTy;
|
||||
|
||||
/// Type used for iterating through the global value summary map.
|
||||
typedef GlobalValueSummaryMapTy::const_iterator const_gvsummary_iterator;
|
||||
typedef GlobalValueSummaryMapTy::iterator gvsummary_iterator;
|
||||
@ -532,6 +515,11 @@ class ModuleSummaryIndex {
|
||||
// YAML I/O support.
|
||||
friend yaml::MappingTraits<ModuleSummaryIndex>;
|
||||
|
||||
GlobalValueSummaryMapTy::value_type *
|
||||
getOrInsertValuePtr(GlobalValue::GUID GUID) {
|
||||
return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first;
|
||||
}
|
||||
|
||||
public:
|
||||
gvsummary_iterator begin() { return GlobalValueMap.begin(); }
|
||||
const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); }
|
||||
@ -539,21 +527,22 @@ class ModuleSummaryIndex {
|
||||
const_gvsummary_iterator end() const { return GlobalValueMap.end(); }
|
||||
size_t size() const { return GlobalValueMap.size(); }
|
||||
|
||||
/// Get the list of global value summary objects for a given value name.
|
||||
const GlobalValueSummaryList &getGlobalValueSummaryList(StringRef ValueName) {
|
||||
return GlobalValueMap[GlobalValue::getGUID(ValueName)];
|
||||
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
|
||||
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
|
||||
auto I = GlobalValueMap.find(GUID);
|
||||
return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I);
|
||||
}
|
||||
|
||||
/// Get the list of global value summary objects for a given value name.
|
||||
const const_gvsummary_iterator
|
||||
findGlobalValueSummaryList(StringRef ValueName) const {
|
||||
return GlobalValueMap.find(GlobalValue::getGUID(ValueName));
|
||||
/// Return a ValueInfo for \p GUID.
|
||||
ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) {
|
||||
return ValueInfo(getOrInsertValuePtr(GUID));
|
||||
}
|
||||
|
||||
/// Get the list of global value summary objects for a given value GUID.
|
||||
const const_gvsummary_iterator
|
||||
findGlobalValueSummaryList(GlobalValue::GUID ValueGUID) const {
|
||||
return GlobalValueMap.find(ValueGUID);
|
||||
/// Return a ValueInfo for \p GV and mark it as belonging to GV.
|
||||
ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
|
||||
auto VP = getOrInsertValuePtr(GV->getGUID());
|
||||
VP->second.GV = GV;
|
||||
return ValueInfo(VP);
|
||||
}
|
||||
|
||||
/// Return the GUID for \p OriginalId in the OidGuidMap.
|
||||
@ -565,17 +554,18 @@ class ModuleSummaryIndex {
|
||||
/// Add a global value summary for a value of the given name.
|
||||
void addGlobalValueSummary(StringRef ValueName,
|
||||
std::unique_ptr<GlobalValueSummary> Summary) {
|
||||
addOriginalName(GlobalValue::getGUID(ValueName),
|
||||
Summary->getOriginalName());
|
||||
GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(
|
||||
std::move(Summary));
|
||||
addGlobalValueSummary(getOrInsertValueInfo(GlobalValue::getGUID(ValueName)),
|
||||
std::move(Summary));
|
||||
}
|
||||
|
||||
/// Add a global value summary for a value of the given GUID.
|
||||
void addGlobalValueSummary(GlobalValue::GUID ValueGUID,
|
||||
/// Add a global value summary for the given ValueInfo.
|
||||
void addGlobalValueSummary(ValueInfo VI,
|
||||
std::unique_ptr<GlobalValueSummary> Summary) {
|
||||
addOriginalName(ValueGUID, Summary->getOriginalName());
|
||||
GlobalValueMap[ValueGUID].push_back(std::move(Summary));
|
||||
addOriginalName(VI.getGUID(), Summary->getOriginalName());
|
||||
// Here we have a notionally const VI, but the value it points to is owned
|
||||
// by the non-const *this.
|
||||
const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref)
|
||||
->second.SummaryList.push_back(std::move(Summary));
|
||||
}
|
||||
|
||||
/// Add an original name for the value of the given GUID.
|
||||
@ -593,16 +583,16 @@ class ModuleSummaryIndex {
|
||||
/// not found.
|
||||
GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
|
||||
StringRef ModuleId) const {
|
||||
auto CalleeInfoList = findGlobalValueSummaryList(ValueGUID);
|
||||
if (CalleeInfoList == end()) {
|
||||
auto CalleeInfo = getValueInfo(ValueGUID);
|
||||
if (!CalleeInfo) {
|
||||
return nullptr; // This function does not have a summary
|
||||
}
|
||||
auto Summary =
|
||||
llvm::find_if(CalleeInfoList->second,
|
||||
llvm::find_if(CalleeInfo.getSummaryList(),
|
||||
[&](const std::unique_ptr<GlobalValueSummary> &Summary) {
|
||||
return Summary->modulePath() == ModuleId;
|
||||
});
|
||||
if (Summary == CalleeInfoList->second.end())
|
||||
if (Summary == CalleeInfo.getSummaryList().end())
|
||||
return nullptr;
|
||||
return Summary->get();
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
|
||||
for (auto &FSum : FSums) {
|
||||
GlobalValueSummary::GVFlags GVFlags(GlobalValue::ExternalLinkage, false,
|
||||
false);
|
||||
Elem.push_back(llvm::make_unique<FunctionSummary>(
|
||||
Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>(
|
||||
GVFlags, 0, ArrayRef<ValueInfo>{},
|
||||
ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
|
||||
std::move(FSum.TypeTestAssumeVCalls),
|
||||
@ -213,7 +213,7 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
|
||||
static void output(IO &io, GlobalValueSummaryMapTy &V) {
|
||||
for (auto &P : V) {
|
||||
std::vector<FunctionSummaryYaml> FSums;
|
||||
for (auto &Sum : P.second) {
|
||||
for (auto &Sum : P.second.SummaryList) {
|
||||
if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
|
||||
FSums.push_back(FunctionSummaryYaml{
|
||||
FSum->type_tests(), FSum->type_test_assume_vcalls(),
|
||||
|
@ -63,6 +63,8 @@ class ConstantPool {
|
||||
|
||||
// Return true if the constant pool is empty
|
||||
bool empty();
|
||||
|
||||
void clearCache();
|
||||
};
|
||||
|
||||
class AssemblerConstantPools {
|
||||
@ -86,6 +88,7 @@ class AssemblerConstantPools {
|
||||
public:
|
||||
void emitAll(MCStreamer &Streamer);
|
||||
void emitForCurrentSection(MCStreamer &Streamer);
|
||||
void clearCacheForCurrentSection(MCStreamer &Streamer);
|
||||
const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr,
|
||||
unsigned Size, SMLoc Loc);
|
||||
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/BinaryByteStream.h"
|
||||
#include "llvm/Support/COFF.h"
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
@ -40,6 +42,7 @@ class DelayImportDirectoryEntryRef;
|
||||
class ExportDirectoryEntryRef;
|
||||
class ImportDirectoryEntryRef;
|
||||
class ImportedSymbolRef;
|
||||
class ResourceSectionRef;
|
||||
|
||||
using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
|
||||
using delay_import_directory_iterator =
|
||||
@ -623,6 +626,26 @@ struct coff_base_reloc_block_entry {
|
||||
int getOffset() const { return Data & ((1 << 12) - 1); }
|
||||
};
|
||||
|
||||
struct coff_resource_dir_entry {
|
||||
union {
|
||||
support::ulittle32_t NameOffset;
|
||||
support::ulittle32_t ID;
|
||||
uint32_t getNameOffset() const {
|
||||
return maskTrailingOnes<uint32_t>(31) & NameOffset;
|
||||
}
|
||||
} Identifier;
|
||||
union {
|
||||
support::ulittle32_t DataEntryOffset;
|
||||
support::ulittle32_t SubdirOffset;
|
||||
|
||||
bool isSubDir() const { return SubdirOffset >> 31; }
|
||||
uint32_t value() const {
|
||||
return maskTrailingOnes<uint32_t>(31) & SubdirOffset;
|
||||
}
|
||||
|
||||
} Offset;
|
||||
};
|
||||
|
||||
struct coff_resource_dir_table {
|
||||
support::ulittle32_t Characteristics;
|
||||
support::ulittle32_t TimeDateStamp;
|
||||
@ -1047,6 +1070,23 @@ class BaseRelocRef {
|
||||
const COFFObjectFile *OwningObject = nullptr;
|
||||
};
|
||||
|
||||
class ResourceSectionRef {
|
||||
public:
|
||||
ResourceSectionRef() = default;
|
||||
explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
|
||||
|
||||
ErrorOr<ArrayRef<UTF16>> getEntryNameString(const coff_resource_dir_entry &Entry);
|
||||
ErrorOr<const coff_resource_dir_table &>
|
||||
getEntrySubDir(const coff_resource_dir_entry &Entry);
|
||||
ErrorOr<const coff_resource_dir_table &> getBaseTable();
|
||||
|
||||
private:
|
||||
BinaryByteStream BBS;
|
||||
|
||||
ErrorOr<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
|
||||
ErrorOr<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
|
||||
};
|
||||
|
||||
// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
|
||||
struct FpoData {
|
||||
support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
|
||||
|
@ -41,10 +41,14 @@ class WasmSymbol {
|
||||
DEBUG_FUNCTION_NAME,
|
||||
};
|
||||
|
||||
WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
|
||||
WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section,
|
||||
uint32_t ElementIndex)
|
||||
: Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex) {}
|
||||
|
||||
StringRef Name;
|
||||
SymbolType Type;
|
||||
uint32_t Section;
|
||||
uint32_t ElementIndex;
|
||||
};
|
||||
|
||||
class WasmSection {
|
||||
|
@ -97,6 +97,11 @@ struct DataSegment {
|
||||
yaml::BinaryRef Content;
|
||||
};
|
||||
|
||||
struct NameEntry {
|
||||
uint32_t Index;
|
||||
StringRef Name;
|
||||
};
|
||||
|
||||
struct Signature {
|
||||
Signature() : Form(wasm::WASM_TYPE_FUNC) {}
|
||||
|
||||
@ -122,6 +127,11 @@ struct CustomSection : Section {
|
||||
|
||||
StringRef Name;
|
||||
yaml::BinaryRef Payload;
|
||||
|
||||
// The follow is used by the "name" custom section.
|
||||
// TODO(sbc): Add support for more then just functions names. The wasm
|
||||
// name section can support multiple sub-sections.
|
||||
std::vector<NameEntry> FunctionNames;
|
||||
};
|
||||
|
||||
struct TypeSection : Section {
|
||||
@ -244,6 +254,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
|
||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
|
||||
|
||||
namespace llvm {
|
||||
@ -297,6 +308,10 @@ template <> struct MappingTraits<WasmYAML::Relocation> {
|
||||
static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<WasmYAML::NameEntry> {
|
||||
static void mapping(IO &IO, WasmYAML::NameEntry &NameEntry);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<WasmYAML::LocalDecl> {
|
||||
static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
|
||||
};
|
||||
|
@ -20,8 +20,7 @@ AARCH64_ARCH("invalid", AK_INVALID, nullptr, nullptr,
|
||||
ARMBuildAttrs::CPUArch::v8_A, FK_NONE, AArch64::AEK_NONE)
|
||||
AARCH64_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A,
|
||||
FK_CRYPTO_NEON_FP_ARMV8,
|
||||
(AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
|
||||
AArch64::AEK_SIMD))
|
||||
(AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD))
|
||||
AARCH64_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a",
|
||||
ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
|
||||
(AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
|
||||
@ -52,38 +51,37 @@ AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras")
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
|
||||
#endif
|
||||
AARCH64_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
|
||||
( AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_NONE))
|
||||
AARCH64_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("exynos-m3", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("falkor", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_CRC))
|
||||
AARCH64_CPU_NAME("thunderx2t99", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_CRC |
|
||||
AArch64::AEK_CRYPTO))
|
||||
(AArch64::AEK_NONE))
|
||||
AARCH64_CPU_NAME("thunderx", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
|
||||
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
|
||||
AARCH64_CPU_NAME("thunderxt88", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
|
||||
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
|
||||
AARCH64_CPU_NAME("thunderxt81", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
|
||||
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
|
||||
AARCH64_CPU_NAME("thunderxt83", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
|
||||
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
|
||||
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
|
||||
// Invalid CPU
|
||||
AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
|
||||
#undef AARCH64_CPU_NAME
|
||||
|
@ -64,8 +64,10 @@ class VarStreamArrayIterator
|
||||
public:
|
||||
VarStreamArrayIterator() = default;
|
||||
VarStreamArrayIterator(const ArrayType &Array, const WrappedCtx &Ctx,
|
||||
BinaryStreamRef Stream, bool *HadError = nullptr)
|
||||
: IterRef(Stream), Ctx(&Ctx), Array(&Array), HadError(HadError) {
|
||||
BinaryStreamRef Stream, bool *HadError = nullptr,
|
||||
uint32_t Offset = 0)
|
||||
: IterRef(Stream), Ctx(&Ctx), Array(&Array), AbsOffset(Offset),
|
||||
HadError(HadError) {
|
||||
if (IterRef.getLength() == 0)
|
||||
moveToEnd();
|
||||
else {
|
||||
@ -115,6 +117,7 @@ class VarStreamArrayIterator
|
||||
for (unsigned I = 0; I < N; ++I) {
|
||||
// We are done with the current record, discard it so that we are
|
||||
// positioned at the next record.
|
||||
AbsOffset += ThisLen;
|
||||
IterRef = IterRef.drop_front(ThisLen);
|
||||
if (IterRef.getLength() == 0) {
|
||||
// There is nothing after the current record, we must make this an end
|
||||
@ -135,6 +138,8 @@ class VarStreamArrayIterator
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t offset() const { return AbsOffset; }
|
||||
|
||||
private:
|
||||
void moveToEnd() {
|
||||
Array = nullptr;
|
||||
@ -152,6 +157,7 @@ class VarStreamArrayIterator
|
||||
const WrappedCtx *Ctx{nullptr};
|
||||
const ArrayType *Array{nullptr};
|
||||
uint32_t ThisLen{0};
|
||||
uint32_t AbsOffset{0};
|
||||
bool HasError{false};
|
||||
bool *HadError{nullptr};
|
||||
};
|
||||
@ -234,7 +240,7 @@ class VarStreamArrayBase {
|
||||
/// since the behavior is undefined if \p Offset does not refer to the
|
||||
/// beginning of a valid record.
|
||||
Iterator at(uint32_t Offset) const {
|
||||
return Iterator(*this, Ctx, Stream.drop_front(Offset), nullptr);
|
||||
return Iterator(*this, Ctx, Stream.drop_front(Offset), nullptr, Offset);
|
||||
}
|
||||
|
||||
BinaryStreamRef getUnderlyingStream() const { return Stream; }
|
||||
@ -338,7 +344,7 @@ template <typename T> class FixedStreamArray {
|
||||
template <typename T>
|
||||
class FixedStreamArrayIterator
|
||||
: public iterator_facade_base<FixedStreamArrayIterator<T>,
|
||||
std::random_access_iterator_tag, T> {
|
||||
std::random_access_iterator_tag, const T> {
|
||||
|
||||
public:
|
||||
FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
|
||||
@ -352,6 +358,7 @@ class FixedStreamArrayIterator
|
||||
}
|
||||
|
||||
const T &operator*() const { return Array[Index]; }
|
||||
const T &operator*() { return Array[Index]; }
|
||||
|
||||
bool operator==(const FixedStreamArrayIterator<T> &R) const {
|
||||
assert(Array == R.Array);
|
||||
|
@ -152,6 +152,30 @@ namespace COFF {
|
||||
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000
|
||||
};
|
||||
|
||||
enum ResourceTypeID {
|
||||
RID_Cursor = 1,
|
||||
RID_Bitmap = 2,
|
||||
RID_Icon = 3,
|
||||
RID_Menu = 4,
|
||||
RID_Dialog = 5,
|
||||
RID_String = 6,
|
||||
RID_FontDir = 7,
|
||||
RID_Font = 8,
|
||||
RID_Accelerator = 9,
|
||||
RID_RCData = 10,
|
||||
RID_MessageTable = 11,
|
||||
RID_Group_Cursor = 12,
|
||||
RID_Group_Icon = 14,
|
||||
RID_Version = 16,
|
||||
RID_DLGInclude = 17,
|
||||
RID_PlugPlay = 19,
|
||||
RID_VXD = 20,
|
||||
RID_AniCursor = 21,
|
||||
RID_AniIcon = 22,
|
||||
RID_HTML = 23,
|
||||
RID_Manifest = 24,
|
||||
};
|
||||
|
||||
struct symbol {
|
||||
char Name[NameSize];
|
||||
uint32_t Value;
|
||||
@ -349,6 +373,26 @@ namespace COFF {
|
||||
IMAGE_REL_ARM_BLX23T = 0x0015
|
||||
};
|
||||
|
||||
enum RelocationTypesARM64 {
|
||||
IMAGE_REL_ARM64_ABSOLUTE = 0x0000,
|
||||
IMAGE_REL_ARM64_ADDR32 = 0x0001,
|
||||
IMAGE_REL_ARM64_ADDR32NB = 0x0002,
|
||||
IMAGE_REL_ARM64_BRANCH26 = 0x0003,
|
||||
IMAGE_REL_ARM64_PAGEBASE_REL2 = 0x0004,
|
||||
IMAGE_REL_ARM64_REL21 = 0x0005,
|
||||
IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006,
|
||||
IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007,
|
||||
IMAGE_REL_ARM64_SECREL = 0x0008,
|
||||
IMAGE_REL_ARM64_SECREL_LOW12A = 0x0009,
|
||||
IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A,
|
||||
IMAGE_REL_ARM64_SECREL_LOW12L = 0x000B,
|
||||
IMAGE_REL_ARM64_TOKEN = 0x000C,
|
||||
IMAGE_REL_ARM64_SECTION = 0x000D,
|
||||
IMAGE_REL_ARM64_ADDR64 = 0x000E,
|
||||
IMAGE_REL_ARM64_BRANCH19 = 0x000F,
|
||||
IMAGE_REL_ARM64_BRANCH14 = 0x0010,
|
||||
};
|
||||
|
||||
enum COMDATType {
|
||||
IMAGE_COMDAT_SELECT_NODUPLICATES = 1,
|
||||
IMAGE_COMDAT_SELECT_ANY,
|
||||
|
@ -24,6 +24,12 @@ struct KnownBits {
|
||||
APInt Zero;
|
||||
APInt One;
|
||||
|
||||
private:
|
||||
// Internal constructor for creating a ConstantRange from two APInts.
|
||||
KnownBits(APInt Zero, APInt One)
|
||||
: Zero(std::move(Zero)), One(std::move(One)) {}
|
||||
|
||||
public:
|
||||
// Default construct Zero and One.
|
||||
KnownBits() {}
|
||||
|
||||
@ -37,6 +43,55 @@ struct KnownBits {
|
||||
return Zero.getBitWidth();
|
||||
}
|
||||
|
||||
/// Returns true if there is conflicting information.
|
||||
bool hasConflict() const { return Zero.intersects(One); }
|
||||
|
||||
/// Returns true if we know the value of all bits.
|
||||
bool isConstant() const {
|
||||
assert(!hasConflict() && "KnownBits conflict!");
|
||||
return Zero.countPopulation() + One.countPopulation() == getBitWidth();
|
||||
}
|
||||
|
||||
/// Returns the value when all bits have a known value. This just returns One
|
||||
/// with a protective assertion.
|
||||
const APInt &getConstant() const {
|
||||
assert(isConstant() && "Can only get value when all bits are known");
|
||||
return One;
|
||||
}
|
||||
|
||||
/// Returns true if we don't know any bits.
|
||||
bool isUnknown() const { return Zero.isNullValue() && One.isNullValue(); }
|
||||
|
||||
/// Resets the known state of all bits.
|
||||
void resetAll() {
|
||||
Zero.clearAllBits();
|
||||
One.clearAllBits();
|
||||
}
|
||||
|
||||
/// Returns true if value is all zero.
|
||||
bool isZero() const {
|
||||
assert(!hasConflict() && "KnownBits conflict!");
|
||||
return Zero.isAllOnesValue();
|
||||
}
|
||||
|
||||
/// Returns true if value is all one bits.
|
||||
bool isAllOnes() const {
|
||||
assert(!hasConflict() && "KnownBits conflict!");
|
||||
return One.isAllOnesValue();
|
||||
}
|
||||
|
||||
/// Make all bits known to be zero and discard any previous information.
|
||||
void setAllZero() {
|
||||
Zero.setAllBits();
|
||||
One.clearAllBits();
|
||||
}
|
||||
|
||||
/// Make all bits known to be one and discard any previous information.
|
||||
void setAllOnes() {
|
||||
Zero.clearAllBits();
|
||||
One.setAllBits();
|
||||
}
|
||||
|
||||
/// Returns true if this value is known to be negative.
|
||||
bool isNegative() const { return One.isSignBitSet(); }
|
||||
|
||||
@ -54,6 +109,30 @@ struct KnownBits {
|
||||
assert(!isNegative() && "Can't make a negative value non-negative");
|
||||
Zero.setSignBit();
|
||||
}
|
||||
|
||||
/// Truncate the underlying known Zero and One bits. This is equivalent
|
||||
/// to truncating the value we're tracking.
|
||||
KnownBits trunc(unsigned BitWidth) {
|
||||
return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
|
||||
}
|
||||
|
||||
/// Zero extends the underlying known Zero and One bits. This is equivalent
|
||||
/// to zero extending the value we're tracking.
|
||||
KnownBits zext(unsigned BitWidth) {
|
||||
return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
|
||||
}
|
||||
|
||||
/// Sign extends the underlying known Zero and One bits. This is equivalent
|
||||
/// to sign extending the value we're tracking.
|
||||
KnownBits sext(unsigned BitWidth) {
|
||||
return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
|
||||
}
|
||||
|
||||
/// Zero extends or truncates the underlying known Zero and One bits. This is
|
||||
/// equivalent to zero extending or truncating the value we're tracking.
|
||||
KnownBits zextOrTrunc(unsigned BitWidth) {
|
||||
return KnownBits(Zero.zextOrTrunc(BitWidth), One.zextOrTrunc(BitWidth));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -214,6 +214,18 @@ template <typename T> T maskLeadingOnes(unsigned N) {
|
||||
return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
|
||||
}
|
||||
|
||||
/// \brief Create a bitmask with the N right-most bits set to 0, and all other
|
||||
/// bits set to 1. Only unsigned types are allowed.
|
||||
template <typename T> T maskTrailingZeros(unsigned N) {
|
||||
return maskLeadingOnes<T>(CHAR_BIT * sizeof(T) - N);
|
||||
}
|
||||
|
||||
/// \brief Create a bitmask with the N left-most bits set to 0, and all other
|
||||
/// bits set to 1. Only unsigned types are allowed.
|
||||
template <typename T> T maskLeadingZeros(unsigned N) {
|
||||
return maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
|
||||
}
|
||||
|
||||
/// \brief Get the index of the last set bit starting from the least
|
||||
/// significant bit.
|
||||
///
|
||||
|
@ -25,25 +25,43 @@ class GINodeEquiv<Instruction i, SDNode node> {
|
||||
SDNode Node = node;
|
||||
}
|
||||
|
||||
def : GINodeEquiv<G_ZEXT, zext>;
|
||||
// These are defined in the same order as the G_* instructions.
|
||||
def : GINodeEquiv<G_ANYEXT, anyext>;
|
||||
def : GINodeEquiv<G_SEXT, sext>;
|
||||
def : GINodeEquiv<G_ZEXT, zext>;
|
||||
def : GINodeEquiv<G_TRUNC, trunc>;
|
||||
def : GINodeEquiv<G_BITCAST, bitconvert>;
|
||||
// G_INTTOPTR - SelectionDAG has no equivalent.
|
||||
// G_PTRTOINT - SelectionDAG has no equivalent.
|
||||
// G_CONSTANT - Not needed since constants aren't operators.
|
||||
// G_FCONSTANT - Not needed since constants aren't operators.
|
||||
def : GINodeEquiv<G_ADD, add>;
|
||||
def : GINodeEquiv<G_SUB, sub>;
|
||||
def : GINodeEquiv<G_MUL, mul>;
|
||||
|
||||
def : GINodeEquiv<G_OR, or>;
|
||||
def : GINodeEquiv<G_XOR, xor>;
|
||||
def : GINodeEquiv<G_AND, and>;
|
||||
|
||||
def : GINodeEquiv<G_SHL, shl>;
|
||||
def : GINodeEquiv<G_LSHR, srl>;
|
||||
def : GINodeEquiv<G_ASHR, sra>;
|
||||
|
||||
def : GINodeEquiv<G_SDIV, sdiv>;
|
||||
def : GINodeEquiv<G_UDIV, udiv>;
|
||||
def : GINodeEquiv<G_SREM, srem>;
|
||||
def : GINodeEquiv<G_UREM, urem>;
|
||||
|
||||
def : GINodeEquiv<G_AND, and>;
|
||||
def : GINodeEquiv<G_OR, or>;
|
||||
def : GINodeEquiv<G_XOR, xor>;
|
||||
def : GINodeEquiv<G_SHL, shl>;
|
||||
def : GINodeEquiv<G_LSHR, srl>;
|
||||
def : GINodeEquiv<G_ASHR, sra>;
|
||||
def : GINodeEquiv<G_SELECT, select>;
|
||||
def : GINodeEquiv<G_FNEG, fneg>;
|
||||
def : GINodeEquiv<G_FPEXT, fpextend>;
|
||||
def : GINodeEquiv<G_FPTRUNC, ftrunc>;
|
||||
def : GINodeEquiv<G_FPTOSI, fp_to_sint>;
|
||||
def : GINodeEquiv<G_FPTOUI, fp_to_uint>;
|
||||
def : GINodeEquiv<G_SITOFP, sint_to_fp>;
|
||||
def : GINodeEquiv<G_UITOFP, uint_to_fp>;
|
||||
def : GINodeEquiv<G_FADD, fadd>;
|
||||
def : GINodeEquiv<G_FSUB, fsub>;
|
||||
def : GINodeEquiv<G_FMUL, fmul>;
|
||||
def : GINodeEquiv<G_FDIV, fdiv>;
|
||||
def : GINodeEquiv<G_FREM, frem>;
|
||||
def : GINodeEquiv<G_FPOW, fpow>;
|
||||
def : GINodeEquiv<G_BR, br>;
|
||||
|
||||
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
|
||||
|
@ -1002,6 +1002,16 @@ def PATCHABLE_TAIL_CALL : Instruction {
|
||||
let hasSideEffects = 1;
|
||||
let isReturn = 1;
|
||||
}
|
||||
def PATCHABLE_EVENT_CALL : Instruction {
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins ptr_rc:$event, i8imm:$size);
|
||||
let AsmString = "# XRay Custom Event Log.";
|
||||
let usesCustomInserter = 1;
|
||||
let isCall = 1;
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 1;
|
||||
}
|
||||
def FENTRY_CALL : Instruction {
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins variable_ops);
|
||||
|
@ -182,6 +182,10 @@ HANDLE_TARGET_OPCODE(PATCHABLE_FUNCTION_EXIT)
|
||||
/// PATCHABLE_RET which specifically only works for return instructions.
|
||||
HANDLE_TARGET_OPCODE(PATCHABLE_TAIL_CALL)
|
||||
|
||||
/// Wraps a logging call and its arguments with nop sleds. At runtime, this can be
|
||||
/// patched to insert instrumentation instructions.
|
||||
HANDLE_TARGET_OPCODE(PATCHABLE_EVENT_CALL)
|
||||
|
||||
/// The following generic opcodes are not supposed to appear after ISel.
|
||||
/// This is something we might want to relax, but for now, this is convenient
|
||||
/// to produce diagnostics.
|
||||
|
@ -177,6 +177,7 @@ struct SanitizerCoverageOptions {
|
||||
bool Use8bitCounters = false;
|
||||
bool TracePC = false;
|
||||
bool TracePCGuard = false;
|
||||
bool NoPrune = false;
|
||||
|
||||
SanitizerCoverageOptions() = default;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user