Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306956, and update

build glue.
This commit is contained in:
Dimitry Andric 2017-07-02 11:41:15 +00:00
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang500-import/; revision=320572
785 changed files with 16632 additions and 10444 deletions

View File

@ -160,7 +160,11 @@ struct QuarantineCallback {
}
void *Allocate(uptr size) {
return get_allocator().Allocate(cache_, size, 1);
void *res = get_allocator().Allocate(cache_, size, 1);
// TODO(alekseys): Consider making quarantine OOM-friendly.
if (UNLIKELY(!res))
return DieOnFailure::OnOOM();
return res;
}
void Deallocate(void *p) {
@ -524,8 +528,7 @@ struct Allocator {
// Expects the chunk to already be marked as quarantined by using
// AtomicallySetQuarantineFlagIfAllocated.
void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
AllocType alloc_type) {
void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack) {
CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
CHECK_GE(m->alloc_tid, 0);
if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area.
@ -603,7 +606,7 @@ struct Allocator {
ReportNewDeleteSizeMismatch(p, delete_size, stack);
}
QuarantineChunk(m, ptr, stack, alloc_type);
QuarantineChunk(m, ptr, stack);
}
void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) {
@ -632,7 +635,7 @@ struct Allocator {
}
void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
if (CallocShouldReturnNullDueToOverflow(size, nmemb))
if (CheckForCallocOverflow(size, nmemb))
return AsanAllocator::FailureHandler::OnBadRequest();
void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false);
// If the memory comes from the secondary allocator no need to clear it

View File

@ -579,17 +579,6 @@ INTERCEPTOR(char*, __strdup, const char *s) {
}
#endif // ASAN_INTERCEPT___STRDUP
INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, wcslen);
SIZE_T length = internal_wcslen(s);
if (!asan_init_is_running) {
ENSURE_ASAN_INITED();
ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t));
}
return length;
}
INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strncpy);
@ -722,7 +711,6 @@ void InitializeAsanInterceptors() {
// Intercept str* functions.
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
ASAN_INTERCEPT_FUNC(wcslen);
ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup);

View File

@ -25,22 +25,26 @@
// dllexport would normally do. We need to export them in order to make the
// VS2015 dynamic CRT (MD) work.
#if SANITIZER_WINDOWS
# define CXX_OPERATOR_ATTRIBUTE
# ifdef _WIN64
# pragma comment(linker, "/export:??2@YAPEAX_K@Z") // operator new
# pragma comment(linker, "/export:??3@YAXPEAX@Z") // operator delete
# pragma comment(linker, "/export:??3@YAXPEAX_K@Z") // sized operator delete
# pragma comment(linker, "/export:??_U@YAPEAX_K@Z") // operator new[]
# pragma comment(linker, "/export:??_V@YAXPEAX@Z") // operator delete[]
# else
# pragma comment(linker, "/export:??2@YAPAXI@Z") // operator new
# pragma comment(linker, "/export:??3@YAXPAX@Z") // operator delete
# pragma comment(linker, "/export:??3@YAXPAXI@Z") // sized operator delete
# pragma comment(linker, "/export:??_U@YAPAXI@Z") // operator new[]
# pragma comment(linker, "/export:??_V@YAXPAX@Z") // operator delete[]
# endif
#define CXX_OPERATOR_ATTRIBUTE
#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:"##sym))
#ifdef _WIN64
COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new
COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow
COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete
COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete
COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[]
COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[]
#else
# define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
COMMENT_EXPORT("??2@YAPAXI@Z") // operator new
COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow
COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete
COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete
COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[]
COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[]
#endif
#undef COMMENT_EXPORT
#else
#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
#endif
using namespace __asan; // NOLINT
@ -63,12 +67,17 @@ struct nothrow_t {};
enum class align_val_t: size_t {};
} // namespace std
#define OPERATOR_NEW_BODY(type) \
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
#define OPERATOR_NEW_BODY(type, nothrow) \
GET_STACK_TRACE_MALLOC;\
return asan_memalign(0, size, &stack, type);
#define OPERATOR_NEW_BODY_ALIGN(type) \
void *res = asan_memalign(0, size, &stack, type);\
if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
return res;
#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
GET_STACK_TRACE_MALLOC;\
return asan_memalign((uptr)align, size, &stack, type);
void *res = asan_memalign((uptr)align, size, &stack, type);\
if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
return res;
// On OS X it's not enough to just provide our own 'operator new' and
// 'operator delete' implementations, because they're going to be in the
@ -79,40 +88,42 @@ enum class align_val_t: size_t {};
// OS X we need to intercept them using their mangled names.
#if !SANITIZER_MAC
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
void *operator new(size_t size)
{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); }
void *operator new[](size_t size)
{ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(FROM_NEW); }
{ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(FROM_NEW_BR); }
{ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::align_val_t align)
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW); }
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::align_val_t align)
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR); }
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&)
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW); }
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); }
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&)
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR); }
{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); }
#else // SANITIZER_MAC
INTERCEPTOR(void *, _Znwm, size_t size) {
OPERATOR_NEW_BODY(FROM_NEW);
OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
}
INTERCEPTOR(void *, _Znam, size_t size) {
OPERATOR_NEW_BODY(FROM_NEW_BR);
OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
}
INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(FROM_NEW);
OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
}
INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(FROM_NEW_BR);
OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
}
#endif

View File

@ -85,6 +85,7 @@ INTERCEPT_LIBRARY_FUNCTION(strstr);
INTERCEPT_LIBRARY_FUNCTION(strtok);
INTERCEPT_LIBRARY_FUNCTION(strtol);
INTERCEPT_LIBRARY_FUNCTION(wcslen);
INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
#ifdef _WIN64
INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);

View File

@ -74,7 +74,7 @@ void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
size = 1;
if (size > kMaxAllowedMallocSize) {
Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", size);
return nullptr;
return Allocator::FailureHandler::OnBadRequest();
}
void *p = allocator.Allocate(GetAllocatorCache(), size, alignment);
// Do not rely on the allocator to clear the memory (it's slow).
@ -99,7 +99,7 @@ void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
if (new_size > kMaxAllowedMallocSize) {
Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", new_size);
allocator.Deallocate(GetAllocatorCache(), p);
return nullptr;
return Allocator::FailureHandler::OnBadRequest();
}
p = allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment);
RegisterAllocation(stack, p, new_size);
@ -134,6 +134,8 @@ void *lsan_realloc(void *p, uptr size, const StackTrace &stack) {
}
void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) {
if (CheckForCallocOverflow(size, nmemb))
return Allocator::FailureHandler::OnBadRequest();
size *= nmemb;
return Allocate(stack, size, 1, true);
}

View File

@ -70,7 +70,6 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
CHECK(allocated < kCallocPoolSize);
return mem;
}
if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return nullptr;
ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC;
return lsan_calloc(nmemb, size, stack);
@ -199,24 +198,38 @@ INTERCEPTOR(int, mprobe, void *ptr) {
}
#endif // SANITIZER_INTERCEPT_MCHECK_MPROBE
#define OPERATOR_NEW_BODY \
ENSURE_LSAN_INITED; \
GET_STACK_TRACE_MALLOC; \
return Allocate(stack, size, 1, kAlwaysClearMemory);
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
#define OPERATOR_NEW_BODY(nothrow) \
ENSURE_LSAN_INITED; \
GET_STACK_TRACE_MALLOC; \
void *res = Allocate(stack, size, 1, kAlwaysClearMemory);\
if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
return res;
#define OPERATOR_DELETE_BODY \
ENSURE_LSAN_INITED; \
Deallocate(ptr);
// On OS X it's not enough to just provide our own 'operator new' and
// 'operator delete' implementations, because they're going to be in the runtime
// dylib, and the main executable will depend on both the runtime dylib and
// libstdc++, each of has its implementation of new and delete.
// To make sure that C++ allocation/deallocation operators are overridden on
// OS X we need to intercept them using their mangled names.
#if !SANITIZER_MAC
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(true /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(true /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
@ -224,9 +237,31 @@ void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
INTERCEPTOR_ATTRIBUTE
void operator delete[](void *ptr, std::nothrow_t const &) {
OPERATOR_DELETE_BODY;
}
void operator delete[](void *ptr, std::nothrow_t const &)
{ OPERATOR_DELETE_BODY; }
#else // SANITIZER_MAC
INTERCEPTOR(void *, _Znwm, size_t size)
{ OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR(void *, _Znam, size_t size)
{ OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(true /*nothrow*/); }
INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(true /*nothrow*/); }
INTERCEPTOR(void, _ZdlPv, void *ptr)
{ OPERATOR_DELETE_BODY; }
INTERCEPTOR(void, _ZdaPv, void *ptr)
{ OPERATOR_DELETE_BODY; }
INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
{ OPERATOR_DELETE_BODY; }
INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&)
{ OPERATOR_DELETE_BODY; }
#endif // !SANITIZER_MAC
///// Thread initialization and finalization. /////

View File

@ -195,7 +195,7 @@ void MsanDeallocate(StackTrace *stack, void *p) {
}
void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
if (CallocShouldReturnNullDueToOverflow(size, nmemb))
if (CheckForCallocOverflow(size, nmemb))
return Allocator::FailureHandler::OnBadRequest();
return MsanReallocate(stack, nullptr, nmemb * size, sizeof(u64), true);
}

View File

@ -538,49 +538,6 @@ INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
return res;
}
INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
ENSURE_MSAN_INITED();
SIZE_T res = REAL(wcslen)(s);
CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
return res;
}
INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
ENSURE_MSAN_INITED();
SIZE_T res = REAL(wcsnlen)(s, n);
CHECK_UNPOISONED(s, sizeof(wchar_t) * Min(res + 1, n));
return res;
}
// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
ENSURE_MSAN_INITED();
wchar_t *res = REAL(wcschr)(s, wc, ps);
return res;
}
// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wcscpy)(dest, src);
CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
&stack);
return res;
}
INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src,
SIZE_T n) { // NOLINT
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
SIZE_T copy_size = REAL(wcsnlen)(src, n);
if (copy_size < n) copy_size++; // trailing \0
wchar_t *res = REAL(wcsncpy)(dest, src, n); // NOLINT
CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
__msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
return res;
}
// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
ENSURE_MSAN_INITED();
@ -1344,11 +1301,11 @@ int OnExit() {
return __msan_memcpy(to, from, size); \
}
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
do { \
GET_STORE_STACK_TRACE; \
CopyShadowAndOrigin(to, from, size, &stack); \
__msan_unpoison(to + size, 1); \
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
do { \
GET_STORE_STACK_TRACE; \
CopyShadowAndOrigin(to, from, size, &stack); \
__msan_unpoison(to + size, 1); \
} while (false)
#include "sanitizer_common/sanitizer_platform_interceptors.h"
@ -1424,6 +1381,35 @@ INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
return res;
}
// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
ENSURE_MSAN_INITED();
wchar_t *res = REAL(wcschr)(s, wc, ps);
return res;
}
// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wcscpy)(dest, src);
CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
&stack);
return res;
}
INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src,
SIZE_T n) { // NOLINT
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
SIZE_T copy_size = REAL(wcsnlen)(src, n);
if (copy_size < n) copy_size++; // trailing \0
wchar_t *res = REAL(wcsncpy)(dest, src, n); // NOLINT
CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
__msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
return res;
}
// These interface functions reside here so that they can use
// REAL(memset), etc.
void __msan_unpoison(const void *a, uptr size) {

View File

@ -14,6 +14,7 @@
#include "msan.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_allocator.h"
#if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
@ -27,18 +28,25 @@ namespace std {
} // namespace std
#define OPERATOR_NEW_BODY \
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
#define OPERATOR_NEW_BODY(nothrow) \
GET_MALLOC_STACK_TRACE; \
return MsanReallocate(&stack, 0, size, sizeof(u64), false)
void *res = MsanReallocate(&stack, 0, size, sizeof(u64), false);\
if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
return res
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY; }
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size) { OPERATOR_NEW_BODY; }
void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
void *operator new(size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(true /*nothrow*/);
}
INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
void *operator new[](size_t size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(true /*nothrow*/);
}
#define OPERATOR_DELETE_BODY \
GET_MALLOC_STACK_TRACE; \

View File

@ -19,8 +19,6 @@
COMPILER_RT_WEAK uint64_t INSTR_PROF_RAW_VERSION_VAR = INSTR_PROF_RAW_VERSION;
COMPILER_RT_WEAK char INSTR_PROF_PROFILE_NAME_VAR[1] = {0};
COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) {
return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64)
: (INSTR_PROF_RAW_MAGIC_32);

View File

@ -45,15 +45,24 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
(CountersEnd - CountersBegin) * sizeof(uint64_t) + NamesSize + Padding;
}
COMPILER_RT_VISIBILITY
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer) {
BufferWriter->Write = lprofBufferWriter;
BufferWriter->WriterCtx = Buffer;
}
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
return lprofWriteData(lprofBufferWriter, Buffer, 0);
ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, Buffer);
return lprofWriteData(&BufferWriter, 0, 0);
}
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
char *Buffer, const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
CountersBegin, CountersEnd, 0, NamesBegin,
NamesEnd);
ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, Buffer);
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
CountersEnd, 0, NamesBegin, NamesEnd, 0);
}

View File

@ -91,24 +91,39 @@ static const char *getCurFilename(char *FilenameBuf);
static unsigned doMerging() { return lprofCurFilename.MergePoolSize; }
/* Return 1 if there is an error, otherwise return 0. */
static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
void **WriterCtx) {
static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
uint32_t NumIOVecs) {
uint32_t I;
FILE *File = (FILE *)*WriterCtx;
FILE *File = (FILE *)This->WriterCtx;
for (I = 0; I < NumIOVecs; I++) {
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
IOVecs[I].NumElm)
return 1;
if (IOVecs[I].Data) {
if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
IOVecs[I].NumElm)
return 1;
} else {
if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
return 1;
}
}
return 0;
}
static void initFileWriter(ProfDataWriter *This, FILE *File) {
This->Write = fileWriter;
This->WriterCtx = File;
}
COMPILER_RT_VISIBILITY ProfBufferIO *
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
FreeHook = &free;
DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
VPBufferSize = BufferSz;
return lprofCreateBufferIO(fileWriter, File);
ProfDataWriter *fileWriter =
(ProfDataWriter *)calloc(sizeof(ProfDataWriter), 1);
initFileWriter(fileWriter, File);
ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
IO->OwnFileWriter = 1;
return IO;
}
static void setupIOBuffer() {
@ -122,9 +137,10 @@ static void setupIOBuffer() {
/* Read profile data in \c ProfileFile and merge with in-memory
profile counters. Returns -1 if there is fatal error, otheriwse
0 is returned.
0 is returned. Returning 0 does not mean merge is actually
performed. If merge is actually done, *MergeDone is set to 1.
*/
static int doProfileMerging(FILE *ProfileFile) {
static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
uint64_t ProfileFileSize;
char *ProfileBuffer;
@ -169,6 +185,8 @@ static int doProfileMerging(FILE *ProfileFile) {
__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize);
(void)munmap(ProfileBuffer, ProfileFileSize);
*MergeDone = 1;
return 0;
}
@ -190,7 +208,7 @@ static void createProfileDir(const char *Filename) {
* dumper. With profile merging enabled, each executable as well as any of
* its instrumented shared libraries dump profile data into their own data file.
*/
static FILE *openFileForMerging(const char *ProfileFileName) {
static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
FILE *ProfileFile;
int rc;
@ -199,15 +217,14 @@ static FILE *openFileForMerging(const char *ProfileFileName) {
if (!ProfileFile)
return NULL;
rc = doProfileMerging(ProfileFile);
if (rc || COMPILER_RT_FTRUNCATE(ProfileFile, 0L) ||
rc = doProfileMerging(ProfileFile, MergeDone);
if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
fseek(ProfileFile, 0L, SEEK_SET) == -1) {
PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
strerror(errno));
fclose(ProfileFile);
return NULL;
}
fseek(ProfileFile, 0L, SEEK_SET);
return ProfileFile;
}
@ -216,17 +233,20 @@ static int writeFile(const char *OutputName) {
int RetVal;
FILE *OutputFile;
int MergeDone = 0;
if (!doMerging())
OutputFile = fopen(OutputName, "ab");
else
OutputFile = openFileForMerging(OutputName);
OutputFile = openFileForMerging(OutputName, &MergeDone);
if (!OutputFile)
return -1;
FreeHook = &free;
setupIOBuffer();
RetVal = lprofWriteData(fileWriter, OutputFile, lprofGetVPDataReader());
ProfDataWriter fileWriter;
initFileWriter(&fileWriter, OutputFile);
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
fclose(OutputFile);
return RetVal;

View File

@ -48,17 +48,21 @@ typedef struct ProfDataIOVec {
size_t NumElm;
} ProfDataIOVec;
typedef uint32_t (*WriterCallback)(ProfDataIOVec *, uint32_t NumIOVecs,
void **WriterCtx);
struct ProfDataWriter;
typedef uint32_t (*WriterCallback)(struct ProfDataWriter *This, ProfDataIOVec *,
uint32_t NumIOVecs);
typedef struct ProfDataWriter {
WriterCallback Write;
void *WriterCtx;
} ProfDataWriter;
/*!
* The data structure for buffered IO of profile data.
*/
typedef struct ProfBufferIO {
/* File handle. */
void *File;
/* Low level IO callback. */
WriterCallback FileWriter;
ProfDataWriter *FileWriter;
uint32_t OwnFileWriter;
/* The start of the buffer. */
uint8_t *BufferStart;
/* Total size of the buffer. */
@ -73,7 +77,7 @@ ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz);
/*!
* This is the interface to create a handle for buffered IO.
*/
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File);
ProfBufferIO *lprofCreateBufferIO(ProfDataWriter *FileWriter);
/*!
* The interface to destroy the bufferIO handle and reclaim
@ -96,8 +100,9 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
/* The low level interface to write data into a buffer. It is used as the
* callback by other high level writer methods such as buffered IO writer
* and profile data writer. */
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
void **WriterCtx);
uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
uint32_t NumIOVecs);
void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer);
struct ValueProfData;
struct ValueProfRecord;
@ -133,15 +138,17 @@ typedef struct VPDataReaderType {
uint32_t N);
} VPDataReaderType;
int lprofWriteData(WriterCallback Writer, void *WriterCtx,
VPDataReaderType *VPDataReader);
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
/* Write profile data to destinitation. If SkipNameDataWrite is set to 1,
the name data is already in destintation, we just skip over it. */
int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader,
int SkipNameDataWrite);
int lprofWriteDataImpl(ProfDataWriter *Writer,
const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin,
const uint64_t *CountersEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd);
const char *NamesEnd, int SkipNameDataWrite);
/* Merge value profile data pointed to by SrcValueProfData into
* in-memory profile counters pointed by to DstData. */

View File

@ -0,0 +1,18 @@
//===- InstrProfilingNameVar.c - profile name variable setup --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "InstrProfiling.h"
/* char __llvm_profile_filename[1]
*
* The runtime should only provide its own definition of this symbol when the
* user has not specified one. Set this up by moving the runtime's copy of this
* symbol to an object file within the archive.
*/
COMPILER_RT_WEAK char INSTR_PROF_PROFILE_NAME_VAR[1] = {0};

View File

@ -31,41 +31,44 @@ COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
/* The buffer writer is reponsponsible in keeping writer state
* across the call.
*/
COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs,
uint32_t NumIOVecs,
void **WriterCtx) {
COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataWriter *This,
ProfDataIOVec *IOVecs,
uint32_t NumIOVecs) {
uint32_t I;
char **Buffer = (char **)WriterCtx;
char **Buffer = (char **)&This->WriterCtx;
for (I = 0; I < NumIOVecs; I++) {
size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
memcpy(*Buffer, IOVecs[I].Data, Length);
if (IOVecs[I].Data)
memcpy(*Buffer, IOVecs[I].Data, Length);
*Buffer += Length;
}
return 0;
}
static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
void *File, uint8_t *Buffer, uint32_t BufferSz) {
BufferIO->File = File;
static void llvmInitBufferIO(ProfBufferIO *BufferIO, ProfDataWriter *FileWriter,
uint8_t *Buffer, uint32_t BufferSz) {
BufferIO->FileWriter = FileWriter;
BufferIO->OwnFileWriter = 0;
BufferIO->BufferStart = Buffer;
BufferIO->BufferSz = BufferSz;
BufferIO->CurOffset = 0;
}
COMPILER_RT_VISIBILITY ProfBufferIO *
lprofCreateBufferIO(WriterCallback FileWriter, void *File) {
lprofCreateBufferIO(ProfDataWriter *FileWriter) {
uint8_t *Buffer = DynamicBufferIOBuffer;
uint32_t BufferSize = VPBufferSize;
if (!Buffer) {
Buffer = &BufferIOBuffer[0];
BufferSize = sizeof(BufferIOBuffer);
}
llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize);
llvmInitBufferIO(&TheBufferIO, FileWriter, Buffer, BufferSize);
return &TheBufferIO;
}
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
if (BufferIO->OwnFileWriter)
FreeHook(BufferIO->FileWriter);
if (DynamicBufferIOBuffer) {
FreeHook(DynamicBufferIOBuffer);
DynamicBufferIOBuffer = 0;
@ -83,13 +86,16 @@ lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) {
/* Special case, bypass the buffer completely. */
ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}};
if (Size > BufferIO->BufferSz) {
if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
return -1;
} else {
/* Write the data to buffer */
uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset;
lprofBufferWriter(IO, 1, (void **)&Buffer);
BufferIO->CurOffset = Buffer - BufferIO->BufferStart;
ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, (char *)Buffer);
lprofBufferWriter(&BufferWriter, IO, 1);
BufferIO->CurOffset =
(uint8_t *)BufferWriter.WriterCtx - BufferIO->BufferStart;
}
return 0;
}
@ -98,7 +104,7 @@ COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
if (BufferIO->CurOffset) {
ProfDataIOVec IO[] = {
{BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}};
if (BufferIO->FileWriter(IO, 1, &BufferIO->File))
if (BufferIO->FileWriter->Write(BufferIO->FileWriter, IO, 1))
return -1;
BufferIO->CurOffset = 0;
}
@ -201,7 +207,7 @@ static int writeOneValueProfData(ProfBufferIO *BufferIO,
return 0;
}
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
static int writeValueProfData(ProfDataWriter *Writer,
VPDataReaderType *VPDataReader,
const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd) {
@ -211,7 +217,7 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
if (!VPDataReader)
return 0;
BufferIO = lprofCreateBufferIO(Writer, WriterCtx);
BufferIO = lprofCreateBufferIO(Writer);
for (DI = DataBegin; DI < DataEnd; DI++) {
if (writeOneValueProfData(BufferIO, VPDataReader, DI))
@ -225,9 +231,9 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
return 0;
}
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
void *WriterCtx,
VPDataReaderType *VPDataReader) {
COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer,
VPDataReaderType *VPDataReader,
int SkipNameDataWrite) {
/* Match logic in __llvm_profile_write_buffer(). */
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
@ -235,18 +241,17 @@ COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
const uint64_t *CountersEnd = __llvm_profile_end_counters();
const char *NamesBegin = __llvm_profile_begin_names();
const char *NamesEnd = __llvm_profile_end_names();
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
CountersBegin, CountersEnd, VPDataReader,
NamesBegin, NamesEnd);
return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin,
CountersEnd, VPDataReader, NamesBegin, NamesEnd,
SkipNameDataWrite);
}
COMPILER_RT_VISIBILITY int
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
const __llvm_profile_data *DataBegin,
lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd) {
const char *NamesEnd, int SkipNameDataWrite) {
/* Calculate size of sections. */
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
@ -268,14 +273,14 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
#include "InstrProfData.inc"
/* Write the data. */
ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1},
{DataBegin, sizeof(__llvm_profile_data), DataSize},
{CountersBegin, sizeof(uint64_t), CountersSize},
{NamesBegin, sizeof(uint8_t), NamesSize},
{Zeroes, sizeof(uint8_t), Padding}};
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
ProfDataIOVec IOVec[] = {
{&Header, sizeof(__llvm_profile_header), 1},
{DataBegin, sizeof(__llvm_profile_data), DataSize},
{CountersBegin, sizeof(uint64_t), CountersSize},
{SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize},
{Zeroes, sizeof(uint8_t), Padding}};
if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec)))
return -1;
return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
DataEnd);
return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd);
}

View File

@ -160,7 +160,7 @@ void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) {
}
void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
if (CallocShouldReturnNullDueToOverflow(count, size))
if (CheckForCallocOverflow(count, size))
return InternalAllocator::FailureHandler::OnBadRequest();
void *p = InternalAlloc(count * size, cache);
if (p) internal_memset(p, 0, count * size);
@ -202,7 +202,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback) {
low_level_alloc_callback = callback;
}
bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n) {
bool CheckForCallocOverflow(uptr size, uptr n) {
if (!size) return false;
uptr max = (uptr)-1L;
return (max / size) < n;
@ -246,11 +246,11 @@ void *ReturnNullOrDieOnFailure::OnOOM() {
ReportAllocatorCannotReturnNull();
}
void *DieOnFailure::OnBadRequest() {
void NORETURN *DieOnFailure::OnBadRequest() {
ReportAllocatorCannotReturnNull();
}
void *DieOnFailure::OnOOM() {
void NORETURN *DieOnFailure::OnOOM() {
atomic_store_relaxed(&allocator_out_of_memory, 1);
ReportAllocatorCannotReturnNull();
}

View File

@ -39,8 +39,8 @@ struct ReturnNullOrDieOnFailure {
};
// Always dies on the failure.
struct DieOnFailure {
static void *OnBadRequest();
static void *OnOOM();
static void NORETURN *OnBadRequest();
static void NORETURN *OnOOM();
};
// Returns true if allocator detected OOM condition. Can be used to avoid memory
@ -56,8 +56,10 @@ struct NoOpMapUnmapCallback {
// Callback type for iterating over chunks.
typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);
// Returns true if calloc(size, n) should return 0 due to overflow in size*n.
bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n);
// Returns true if calloc(size, n) call overflows on size*n calculation.
// The caller should "return POLICY::OnBadRequest();" where POLICY is the
// current allocator failure handling policy.
bool CheckForCallocOverflow(uptr size, uptr n);
#include "sanitizer_allocator_size_class_map.h"
#include "sanitizer_allocator_stats.h"

View File

@ -46,8 +46,10 @@ struct SizeClassAllocator64LocalCache {
CHECK_NE(class_id, 0UL);
CHECK_LT(class_id, kNumClasses);
PerClass *c = &per_class_[class_id];
if (UNLIKELY(c->count == 0))
Refill(c, allocator, class_id);
if (UNLIKELY(c->count == 0)) {
if (UNLIKELY(!Refill(c, allocator, class_id)))
return nullptr;
}
stats_.Add(AllocatorStatAllocated, c->class_size);
CHECK_GT(c->count, 0);
CompactPtrT chunk = c->chunks[--c->count];
@ -101,13 +103,15 @@ struct SizeClassAllocator64LocalCache {
}
}
NOINLINE void Refill(PerClass *c, SizeClassAllocator *allocator,
NOINLINE bool Refill(PerClass *c, SizeClassAllocator *allocator,
uptr class_id) {
InitCache();
uptr num_requested_chunks = c->max_count / 2;
allocator->GetFromAllocator(&stats_, class_id, c->chunks,
num_requested_chunks);
if (UNLIKELY(!allocator->GetFromAllocator(&stats_, class_id, c->chunks,
num_requested_chunks)))
return false;
c->count = num_requested_chunks;
return true;
}
NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator, uptr class_id,

View File

@ -118,7 +118,6 @@ class SizeClassAllocator32 {
}
void *MapWithCallback(uptr size) {
size = RoundUpTo(size, GetPageSizeCached());
void *res = MmapOrDie(size, "SizeClassAllocator32");
MapUnmapCallback().OnMap((uptr)res, size);
return res;
@ -285,7 +284,7 @@ class SizeClassAllocator32 {
return 0;
MapUnmapCallback().OnMap(res, kRegionSize);
stat->Add(AllocatorStatMapped, kRegionSize);
CHECK_EQ(0U, (res & (kRegionSize - 1)));
CHECK(IsAligned(res, kRegionSize));
possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
return res;
}
@ -303,17 +302,17 @@ class SizeClassAllocator32 {
return false;
uptr n_chunks = kRegionSize / (size + kMetadataSize);
uptr max_count = TransferBatch::MaxCached(class_id);
CHECK_GT(max_count, 0);
TransferBatch *b = nullptr;
for (uptr i = reg; i < reg + n_chunks * size; i += size) {
if (!b) {
b = c->CreateBatch(class_id, this, (TransferBatch*)i);
if (!b)
if (UNLIKELY(!b))
return false;
b->Clear();
}
b->Add((void*)i);
if (b->Count() == max_count) {
CHECK_GT(b->Count(), 0);
sci->free_list.push_back(b);
b = nullptr;
}

View File

@ -80,7 +80,7 @@ class SizeClassAllocator64 {
CHECK_NE(NonConstSpaceBeg, ~(uptr)0);
}
SetReleaseToOSIntervalMs(release_to_os_interval_ms);
MapWithCallback(SpaceEnd(), AdditionalSize());
MapWithCallbackOrDie(SpaceEnd(), AdditionalSize());
}
s32 ReleaseToOSIntervalMs() const {
@ -92,16 +92,6 @@ class SizeClassAllocator64 {
memory_order_relaxed);
}
void MapWithCallback(uptr beg, uptr size) {
CHECK_EQ(beg, reinterpret_cast<uptr>(MmapFixedOrDie(beg, size)));
MapUnmapCallback().OnMap(beg, size);
}
void UnmapWithCallback(uptr beg, uptr size) {
MapUnmapCallback().OnUnmap(beg, size);
UnmapOrDie(reinterpret_cast<void *>(beg), size);
}
static bool CanAllocate(uptr size, uptr alignment) {
return size <= SizeClassMap::kMaxSize &&
alignment <= SizeClassMap::kMaxSize;
@ -116,16 +106,20 @@ class SizeClassAllocator64 {
BlockingMutexLock l(&region->mutex);
uptr old_num_chunks = region->num_freed_chunks;
uptr new_num_freed_chunks = old_num_chunks + n_chunks;
EnsureFreeArraySpace(region, region_beg, new_num_freed_chunks);
// Failure to allocate free array space while releasing memory is non
// recoverable.
if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
new_num_freed_chunks)))
DieOnFailure::OnOOM();
for (uptr i = 0; i < n_chunks; i++)
free_array[old_num_chunks + i] = chunks[i];
region->num_freed_chunks = new_num_freed_chunks;
region->n_freed += n_chunks;
region->stats.n_freed += n_chunks;
MaybeReleaseToOS(class_id);
}
NOINLINE void GetFromAllocator(AllocatorStats *stat, uptr class_id,
NOINLINE bool GetFromAllocator(AllocatorStats *stat, uptr class_id,
CompactPtrT *chunks, uptr n_chunks) {
RegionInfo *region = GetRegionInfo(class_id);
uptr region_beg = GetRegionBeginBySizeClass(class_id);
@ -133,18 +127,19 @@ class SizeClassAllocator64 {
BlockingMutexLock l(&region->mutex);
if (UNLIKELY(region->num_freed_chunks < n_chunks)) {
PopulateFreeArray(stat, class_id, region,
n_chunks - region->num_freed_chunks);
if (UNLIKELY(!PopulateFreeArray(stat, class_id, region,
n_chunks - region->num_freed_chunks)))
return false;
CHECK_GE(region->num_freed_chunks, n_chunks);
}
region->num_freed_chunks -= n_chunks;
uptr base_idx = region->num_freed_chunks;
for (uptr i = 0; i < n_chunks; i++)
chunks[i] = free_array[base_idx + i];
region->n_allocated += n_chunks;
region->stats.n_allocated += n_chunks;
return true;
}
bool PointerIsMine(const void *p) {
uptr P = reinterpret_cast<uptr>(p);
if (kUsingConstantSpaceBeg && (kSpaceBeg % kSpaceSize) == 0)
@ -211,7 +206,7 @@ class SizeClassAllocator64 {
// Test-only.
void TestOnlyUnmap() {
UnmapWithCallback(SpaceBeg(), kSpaceSize + AdditionalSize());
UnmapWithCallbackOrDie(SpaceBeg(), kSpaceSize + AdditionalSize());
}
static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats,
@ -224,15 +219,15 @@ class SizeClassAllocator64 {
void PrintStats(uptr class_id, uptr rss) {
RegionInfo *region = GetRegionInfo(class_id);
if (region->mapped_user == 0) return;
uptr in_use = region->n_allocated - region->n_freed;
uptr in_use = region->stats.n_allocated - region->stats.n_freed;
uptr avail_chunks = region->allocated_user / ClassIdToSize(class_id);
Printf(
" %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
"%s %02zd (%6zd): mapped: %6zdK allocs: %7zd frees: %7zd inuse: %6zd "
"num_freed_chunks %7zd avail: %6zd rss: %6zdK releases: %6zd\n",
class_id, ClassIdToSize(class_id), region->mapped_user >> 10,
region->n_allocated, region->n_freed, in_use,
region->num_freed_chunks, avail_chunks, rss >> 10,
region->rtoi.num_releases);
region->exhausted ? "F" : " ", class_id, ClassIdToSize(class_id),
region->mapped_user >> 10, region->stats.n_allocated,
region->stats.n_freed, in_use, region->num_freed_chunks, avail_chunks,
rss >> 10, region->rtoi.num_releases);
}
void PrintStats() {
@ -242,8 +237,8 @@ class SizeClassAllocator64 {
for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
RegionInfo *region = GetRegionInfo(class_id);
total_mapped += region->mapped_user;
n_allocated += region->n_allocated;
n_freed += region->n_freed;
n_allocated += region->stats.n_allocated;
n_freed += region->stats.n_freed;
}
Printf("Stats: SizeClassAllocator64: %zdM mapped in %zd allocations; "
"remains %zd\n",
@ -326,6 +321,11 @@ class SizeClassAllocator64 {
atomic_sint32_t release_to_os_interval_ms_;
struct Stats {
uptr n_allocated;
uptr n_freed;
};
struct ReleaseToOsInfo {
uptr n_freed_at_last_release;
uptr num_releases;
@ -340,8 +340,9 @@ class SizeClassAllocator64 {
uptr allocated_meta; // Bytes allocated for metadata.
uptr mapped_user; // Bytes mapped for user memory.
uptr mapped_meta; // Bytes mapped for metadata.
u32 rand_state; // Seed for random shuffle, used if kRandomShuffleChunks.
uptr n_allocated, n_freed; // Just stats.
u32 rand_state; // Seed for random shuffle, used if kRandomShuffleChunks.
bool exhausted; // Whether region is out of space for new chunks.
Stats stats;
ReleaseToOsInfo rtoi;
};
COMPILER_CHECK(sizeof(RegionInfo) >= kCacheLineSize);
@ -386,7 +387,26 @@ class SizeClassAllocator64 {
kFreeArraySize);
}
void EnsureFreeArraySpace(RegionInfo *region, uptr region_beg,
bool MapWithCallback(uptr beg, uptr size) {
uptr mapped = reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(beg, size));
if (UNLIKELY(!mapped))
return false;
CHECK_EQ(beg, mapped);
MapUnmapCallback().OnMap(beg, size);
return true;
}
void MapWithCallbackOrDie(uptr beg, uptr size) {
CHECK_EQ(beg, reinterpret_cast<uptr>(MmapFixedOrDie(beg, size)));
MapUnmapCallback().OnMap(beg, size);
}
void UnmapWithCallbackOrDie(uptr beg, uptr size) {
MapUnmapCallback().OnUnmap(beg, size);
UnmapOrDie(reinterpret_cast<void *>(beg), size);
}
bool EnsureFreeArraySpace(RegionInfo *region, uptr region_beg,
uptr num_freed_chunks) {
uptr needed_space = num_freed_chunks * sizeof(CompactPtrT);
if (region->mapped_free_array < needed_space) {
@ -395,66 +415,87 @@ class SizeClassAllocator64 {
uptr current_map_end = reinterpret_cast<uptr>(GetFreeArray(region_beg)) +
region->mapped_free_array;
uptr new_map_size = new_mapped_free_array - region->mapped_free_array;
MapWithCallback(current_map_end, new_map_size);
if (UNLIKELY(!MapWithCallback(current_map_end, new_map_size)))
return false;
region->mapped_free_array = new_mapped_free_array;
}
return true;
}
NOINLINE void PopulateFreeArray(AllocatorStats *stat, uptr class_id,
NOINLINE bool PopulateFreeArray(AllocatorStats *stat, uptr class_id,
RegionInfo *region, uptr requested_count) {
// region->mutex is held.
uptr size = ClassIdToSize(class_id);
uptr beg_idx = region->allocated_user;
uptr end_idx = beg_idx + requested_count * size;
uptr region_beg = GetRegionBeginBySizeClass(class_id);
if (end_idx > region->mapped_user) {
const uptr size = ClassIdToSize(class_id);
const uptr new_space_beg = region->allocated_user;
const uptr new_space_end = new_space_beg + requested_count * size;
const uptr region_beg = GetRegionBeginBySizeClass(class_id);
// Map more space for chunks, if necessary.
if (new_space_end > region->mapped_user) {
if (!kUsingConstantSpaceBeg && region->mapped_user == 0)
region->rand_state = static_cast<u32>(region_beg >> 12); // From ASLR.
// Do the mmap for the user memory.
uptr map_size = kUserMapSize;
while (end_idx > region->mapped_user + map_size)
while (new_space_end > region->mapped_user + map_size)
map_size += kUserMapSize;
CHECK_GE(region->mapped_user + map_size, end_idx);
MapWithCallback(region_beg + region->mapped_user, map_size);
CHECK_GE(region->mapped_user + map_size, new_space_end);
if (UNLIKELY(!MapWithCallback(region_beg + region->mapped_user,
map_size)))
return false;
stat->Add(AllocatorStatMapped, map_size);
region->mapped_user += map_size;
}
CompactPtrT *free_array = GetFreeArray(region_beg);
uptr total_count = (region->mapped_user - beg_idx) / size;
uptr num_freed_chunks = region->num_freed_chunks;
EnsureFreeArraySpace(region, region_beg, num_freed_chunks + total_count);
for (uptr i = 0; i < total_count; i++) {
uptr chunk = beg_idx + i * size;
free_array[num_freed_chunks + total_count - 1 - i] =
PointerToCompactPtr(0, chunk);
}
if (kRandomShuffleChunks)
RandomShuffle(&free_array[num_freed_chunks], total_count,
&region->rand_state);
region->num_freed_chunks += total_count;
region->allocated_user += total_count * size;
CHECK_LE(region->allocated_user, region->mapped_user);
const uptr new_chunks_count = (region->mapped_user - new_space_beg) / size;
region->allocated_meta += total_count * kMetadataSize;
if (region->allocated_meta > region->mapped_meta) {
uptr map_size = kMetaMapSize;
while (region->allocated_meta > region->mapped_meta + map_size)
map_size += kMetaMapSize;
// Do the mmap for the metadata.
CHECK_GE(region->mapped_meta + map_size, region->allocated_meta);
MapWithCallback(GetMetadataEnd(region_beg) -
region->mapped_meta - map_size, map_size);
region->mapped_meta += map_size;
}
CHECK_LE(region->allocated_meta, region->mapped_meta);
if (region->mapped_user + region->mapped_meta >
// Calculate the required space for metadata.
const uptr requested_allocated_meta =
region->allocated_meta + new_chunks_count * kMetadataSize;
uptr requested_mapped_meta = region->mapped_meta;
while (requested_allocated_meta > requested_mapped_meta)
requested_mapped_meta += kMetaMapSize;
// Check whether this size class is exhausted.
if (region->mapped_user + requested_mapped_meta >
kRegionSize - kFreeArraySize) {
Printf("%s: Out of memory. Dying. ", SanitizerToolName);
Printf("The process has exhausted %zuMB for size class %zu.\n",
kRegionSize / 1024 / 1024, size);
Die();
if (!region->exhausted) {
region->exhausted = true;
Printf("%s: Out of memory. ", SanitizerToolName);
Printf("The process has exhausted %zuMB for size class %zu.\n",
kRegionSize >> 20, size);
}
return false;
}
// Map more space for metadata, if necessary.
if (requested_mapped_meta > region->mapped_meta) {
if (UNLIKELY(!MapWithCallback(
GetMetadataEnd(region_beg) - requested_mapped_meta,
requested_mapped_meta - region->mapped_meta)))
return false;
region->mapped_meta = requested_mapped_meta;
}
// If necessary, allocate more space for the free array and populate it with
// newly allocated chunks.
const uptr total_freed_chunks = region->num_freed_chunks + new_chunks_count;
if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg, total_freed_chunks)))
return false;
CompactPtrT *free_array = GetFreeArray(region_beg);
for (uptr i = 0, chunk = new_space_beg; i < new_chunks_count;
i++, chunk += size)
free_array[total_freed_chunks - 1 - i] = PointerToCompactPtr(0, chunk);
if (kRandomShuffleChunks)
RandomShuffle(&free_array[region->num_freed_chunks], new_chunks_count,
&region->rand_state);
// All necessary memory is mapped and now it is safe to advance all
// 'allocated_*' counters.
region->num_freed_chunks += new_chunks_count;
region->allocated_user += new_chunks_count * size;
CHECK_LE(region->allocated_user, region->mapped_user);
region->allocated_meta = requested_allocated_meta;
CHECK_LE(region->allocated_meta, region->mapped_meta);
region->exhausted = false;
return true;
}
void MaybeReleaseChunkRange(uptr region_beg, uptr chunk_size,
@ -478,8 +519,8 @@ class SizeClassAllocator64 {
uptr n = region->num_freed_chunks;
if (n * chunk_size < page_size)
return; // No chance to release anything.
if ((region->n_freed - region->rtoi.n_freed_at_last_release) * chunk_size <
page_size) {
if ((region->stats.n_freed -
region->rtoi.n_freed_at_last_release) * chunk_size < page_size) {
return; // Nothing new to release.
}
@ -508,7 +549,7 @@ class SizeClassAllocator64 {
CHECK_GT(chunk - prev, scaled_chunk_size);
if (prev + scaled_chunk_size - range_beg >= kScaledGranularity) {
MaybeReleaseChunkRange(region_beg, chunk_size, range_beg, prev);
region->rtoi.n_freed_at_last_release = region->n_freed;
region->rtoi.n_freed_at_last_release = region->stats.n_freed;
region->rtoi.num_releases++;
}
range_beg = chunk;
@ -517,5 +558,3 @@ class SizeClassAllocator64 {
}
}
};

View File

@ -92,6 +92,9 @@ void *MmapFixedNoReserve(uptr fixed_addr, uptr size,
const char *name = nullptr);
void *MmapNoReserveOrDie(uptr size, const char *mem_type);
void *MmapFixedOrDie(uptr fixed_addr, uptr size);
// Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
// that case returns nullptr.
void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size);
void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name = nullptr);
void *MmapNoAccess(uptr size);
// Map aligned chunk of address space; size and alignment are powers of two.

View File

@ -224,16 +224,16 @@ bool PlatformHasDifferentMemcpyAndMemmove();
#endif
#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
uptr copy_length = internal_strnlen(s, size); \
char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
if (common_flags()->intercept_strndup) { \
COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
} \
COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
internal_memcpy(new_mem, s, copy_length); \
new_mem[copy_length] = '\0'; \
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
uptr copy_length = internal_strnlen(s, size); \
char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
if (common_flags()->intercept_strndup) { \
COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
} \
COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
internal_memcpy(new_mem, s, copy_length); \
new_mem[copy_length] = '\0'; \
return new_mem;
#endif
@ -6199,6 +6199,57 @@ INTERCEPTOR(int, mprobe, void *ptr) {
}
#endif
INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
SIZE_T res = REAL(wcslen)(s);
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
return res;
}
INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
SIZE_T res = REAL(wcsnlen)(s, n);
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
return res;
}
#define INIT_WCSLEN \
COMMON_INTERCEPT_FUNCTION(wcslen); \
COMMON_INTERCEPT_FUNCTION(wcsnlen);
#if SANITIZER_INTERCEPT_WCSCAT
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
SIZE_T src_size = REAL(wcslen)(src);
SIZE_T dst_size = REAL(wcslen)(dst);
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
(src_size + 1) * sizeof(wchar_t));
return REAL(wcscat)(dst, src); // NOLINT
}
INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
SIZE_T src_size = REAL(wcsnlen)(src, n);
SIZE_T dst_size = REAL(wcslen)(dst);
COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
Min(src_size + 1, n) * sizeof(wchar_t));
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
(src_size + 1) * sizeof(wchar_t));
return REAL(wcsncat)(dst, src, n); // NOLINT
}
#define INIT_WCSCAT \
COMMON_INTERCEPT_FUNCTION(wcscat); \
COMMON_INTERCEPT_FUNCTION(wcsncat);
#else
#define INIT_WCSCAT
#endif
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@ -6403,4 +6454,6 @@ static void InitializeCommonInterceptors() {
INIT_UTMP;
INIT_UTMPX;
INIT_GETLOADAVG;
INIT_WCSLEN;
INIT_WCSCAT;
}

View File

@ -354,5 +354,6 @@
#define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC)
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC)
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_WCSCAT SI_NOT_WINDOWS
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

View File

@ -129,7 +129,7 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
int reserrno;
if (internal_iserror(res, &reserrno))
if (UNLIKELY(internal_iserror(res, &reserrno)))
ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno, raw_report);
IncreaseTotalMmap(size);
return (void *)res;
@ -138,7 +138,7 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
void UnmapOrDie(void *addr, uptr size) {
if (!addr || !size) return;
uptr res = internal_munmap(addr, size);
if (internal_iserror(res)) {
if (UNLIKELY(internal_iserror(res))) {
Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
SanitizerToolName, size, size, addr);
CHECK("unable to unmap" && 0);
@ -152,7 +152,7 @@ void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
int reserrno;
if (internal_iserror(res, &reserrno)) {
if (UNLIKELY(internal_iserror(res, &reserrno))) {
if (reserrno == ENOMEM)
return nullptr;
ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
@ -170,15 +170,15 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
CHECK(IsPowerOfTwo(alignment));
uptr map_size = size + alignment;
uptr map_res = (uptr)MmapOrDieOnFatalError(map_size, mem_type);
if (!map_res)
if (UNLIKELY(!map_res))
return nullptr;
uptr map_end = map_res + map_size;
uptr res = map_res;
if (res & (alignment - 1)) // Not aligned.
res = (map_res + alignment) & ~(alignment - 1);
uptr end = res + size;
if (res != map_res)
if (!IsAligned(res, alignment)) {
res = (map_res + alignment - 1) & ~(alignment - 1);
UnmapOrDie((void*)map_res, res - map_res);
}
uptr end = res + size;
if (end != map_end)
UnmapOrDie((void*)end, map_end - end);
return (void*)res;
@ -192,13 +192,13 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
-1, 0);
int reserrno;
if (internal_iserror(p, &reserrno))
if (UNLIKELY(internal_iserror(p, &reserrno)))
ReportMmapFailureAndDie(size, mem_type, "allocate noreserve", reserrno);
IncreaseTotalMmap(size);
return (void *)p;
}
void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
void *MmapFixedImpl(uptr fixed_addr, uptr size, bool tolerate_enomem) {
uptr PageSize = GetPageSizeCached();
uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
RoundUpTo(size, PageSize),
@ -206,8 +206,10 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-1, 0);
int reserrno;
if (internal_iserror(p, &reserrno)) {
char mem_type[30];
if (UNLIKELY(internal_iserror(p, &reserrno))) {
if (tolerate_enomem && reserrno == ENOMEM)
return nullptr;
char mem_type[40];
internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
fixed_addr);
ReportMmapFailureAndDie(size, mem_type, "allocate", reserrno);
@ -216,6 +218,14 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
return (void *)p;
}
void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
return MmapFixedImpl(fixed_addr, size, false /*tolerate_enomem*/);
}
void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size) {
return MmapFixedImpl(fixed_addr, size, true /*tolerate_enomem*/);
}
bool MprotectNoAccess(uptr addr, uptr size) {
return 0 == internal_mprotect((void*)addr, size, PROT_NONE);
}

View File

@ -235,6 +235,18 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
return p;
}
void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size) {
void *p = VirtualAlloc((LPVOID)fixed_addr, size,
MEM_COMMIT, PAGE_READWRITE);
if (p == 0) {
char mem_type[30];
internal_snprintf(mem_type, sizeof(mem_type), "memory at address 0x%zx",
fixed_addr);
return ReturnNullptrOnOOMOrDie(size, mem_type, "allocate");
}
return p;
}
void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
// FIXME: make this really NoReserve?
return MmapOrDie(size, mem_type);

View File

@ -22,8 +22,7 @@
#include "sanitizer_common/sanitizer_allocator_interface.h"
#include "sanitizer_common/sanitizer_quarantine.h"
#include <limits.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
namespace __scudo {
@ -341,7 +340,7 @@ struct ScudoAllocator {
// Helper function that checks for a valid Scudo chunk. nullptr isn't.
bool isValidPointer(const void *UserPtr) {
initThreadMaybe();
if (!UserPtr)
if (UNLIKELY(!UserPtr))
return false;
uptr UserBeg = reinterpret_cast<uptr>(UserPtr);
if (!IsAligned(UserBeg, MinAlignment))
@ -353,22 +352,19 @@ struct ScudoAllocator {
void *allocate(uptr Size, uptr Alignment, AllocType Type,
bool ForceZeroContents = false) {
initThreadMaybe();
if (UNLIKELY(!IsPowerOfTwo(Alignment))) {
dieWithMessage("ERROR: alignment is not a power of 2\n");
}
if (Alignment > MaxAlignment)
if (UNLIKELY(Alignment > MaxAlignment))
return FailureHandler::OnBadRequest();
if (Alignment < MinAlignment)
if (UNLIKELY(Alignment < MinAlignment))
Alignment = MinAlignment;
if (Size >= MaxAllowedMallocSize)
if (UNLIKELY(Size >= MaxAllowedMallocSize))
return FailureHandler::OnBadRequest();
if (Size == 0)
if (UNLIKELY(Size == 0))
Size = 1;
uptr NeededSize = RoundUpTo(Size, MinAlignment) + AlignedChunkHeaderSize;
uptr AlignedSize = (Alignment > MinAlignment) ?
NeededSize + (Alignment - AlignedChunkHeaderSize) : NeededSize;
if (AlignedSize >= MaxAllowedMallocSize)
if (UNLIKELY(AlignedSize >= MaxAllowedMallocSize))
return FailureHandler::OnBadRequest();
// Primary and Secondary backed allocations have a different treatment. We
@ -393,7 +389,7 @@ struct ScudoAllocator {
Ptr = BackendAllocator.Allocate(&FallbackAllocatorCache, AllocationSize,
AllocationAlignment, FromPrimary);
}
if (!Ptr)
if (UNLIKELY(!Ptr))
return FailureHandler::OnOOM();
// If requested, we will zero out the entire contents of the returned chunk.
@ -404,7 +400,7 @@ struct ScudoAllocator {
UnpackedHeader Header = {};
uptr AllocBeg = reinterpret_cast<uptr>(Ptr);
uptr UserBeg = AllocBeg + AlignedChunkHeaderSize;
if (!IsAligned(UserBeg, Alignment)) {
if (UNLIKELY(!IsAligned(UserBeg, Alignment))) {
// Since the Secondary takes care of alignment, a non-aligned pointer
// means it is from the Primary. It is also the only case where the offset
// field of the header would be non-zero.
@ -481,7 +477,7 @@ struct ScudoAllocator {
void deallocate(void *UserPtr, uptr DeleteSize, AllocType Type) {
initThreadMaybe();
// if (&__sanitizer_free_hook) __sanitizer_free_hook(UserPtr);
if (!UserPtr)
if (UNLIKELY(!UserPtr))
return;
uptr UserBeg = reinterpret_cast<uptr>(UserPtr);
if (UNLIKELY(!IsAligned(UserBeg, MinAlignment))) {
@ -568,7 +564,7 @@ struct ScudoAllocator {
// Helper function that returns the actual usable size of a chunk.
uptr getUsableSize(const void *Ptr) {
initThreadMaybe();
if (!Ptr)
if (UNLIKELY(!Ptr))
return 0;
uptr UserBeg = reinterpret_cast<uptr>(Ptr);
ScudoChunk *Chunk = getScudoChunk(UserBeg);
@ -584,10 +580,9 @@ struct ScudoAllocator {
void *calloc(uptr NMemB, uptr Size) {
initThreadMaybe();
uptr Total = NMemB * Size;
if (Size != 0 && Total / Size != NMemB) // Overflow check
if (CheckForCallocOverflow(NMemB, Size))
return FailureHandler::OnBadRequest();
return allocate(Total, MinAlignment, FromMalloc, true);
return allocate(NMemB * Size, MinAlignment, FromMalloc, true);
}
void commitBack(ScudoThreadContext *ThreadContext) {
@ -655,10 +650,6 @@ void *scudoValloc(uptr Size) {
return Instance.allocate(Size, GetPageSizeCached(), FromMemalign);
}
void *scudoMemalign(uptr Alignment, uptr Size) {
return Instance.allocate(Size, Alignment, FromMemalign);
}
void *scudoPvalloc(uptr Size) {
uptr PageSize = GetPageSizeCached();
Size = RoundUpTo(Size, PageSize);
@ -669,16 +660,27 @@ void *scudoPvalloc(uptr Size) {
return Instance.allocate(Size, PageSize, FromMemalign);
}
void *scudoMemalign(uptr Alignment, uptr Size) {
if (UNLIKELY(!IsPowerOfTwo(Alignment)))
return ScudoAllocator::FailureHandler::OnBadRequest();
return Instance.allocate(Size, Alignment, FromMemalign);
}
int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size) {
if (UNLIKELY(!IsPowerOfTwo(Alignment) || (Alignment % sizeof(void *)) != 0)) {
*MemPtr = ScudoAllocator::FailureHandler::OnBadRequest();
return EINVAL;
}
*MemPtr = Instance.allocate(Size, Alignment, FromMemalign);
if (!*MemPtr)
return ENOMEM;
return 0;
}
void *scudoAlignedAlloc(uptr Alignment, uptr Size) {
// size must be a multiple of the alignment. To avoid a division, we first
// make sure that alignment is a power of 2.
CHECK(IsPowerOfTwo(Alignment));
CHECK_EQ((Size & (Alignment - 1)), 0);
// Alignment must be a power of 2, Size must be a multiple of Alignment.
if (UNLIKELY(!IsPowerOfTwo(Alignment) || (Size & (Alignment - 1)) != 0))
return ScudoAllocator::FailureHandler::OnBadRequest();
return Instance.allocate(Size, Alignment, FromMalloc);
}

View File

@ -116,6 +116,11 @@ struct AP32 {
typedef SizeClassAllocator32<AP32> PrimaryAllocator;
#endif // SANITIZER_CAN_USE_ALLOCATOR64
// __sanitizer::RoundUp has a CHECK that is extraneous for us. Use our own.
INLINE uptr RoundUpTo(uptr Size, uptr Boundary) {
return (Size + Boundary - 1) & ~(Boundary - 1);
}
#include "scudo_allocator_secondary.h"
#include "scudo_allocator_combined.h"

View File

@ -45,7 +45,7 @@ class ScudoCombinedAllocator {
uptr GetActuallyAllocatedSize(void *Ptr, bool FromPrimary) {
if (FromPrimary)
return Primary.GetActuallyAllocatedSize(Ptr);
return PrimaryAllocator::ClassIdToSize(Primary.GetSizeClass(Ptr));
return Secondary.GetActuallyAllocatedSize(Ptr);
}

View File

@ -26,13 +26,18 @@ namespace std {
struct nothrow_t {};
} // namespace std
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size) {
return scudoMalloc(size, FromNew);
void *res = scudoMalloc(size, FromNew);
if (UNLIKELY(!res)) DieOnFailure::OnOOM();
return res;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new[](size_t size) {
return scudoMalloc(size, FromNewArray);
void *res = scudoMalloc(size, FromNewArray);
if (UNLIKELY(!res)) DieOnFailure::OnOOM();
return res;
}
CXX_OPERATOR_ATTRIBUTE
void *operator new(size_t size, std::nothrow_t const&) {

View File

@ -45,7 +45,7 @@ static void initOnce() {
NumberOfContexts = getNumberOfCPUs();
ThreadContexts = reinterpret_cast<ScudoThreadContext *>(
MmapOrDie(sizeof(ScudoThreadContext) * NumberOfContexts, __func__));
for (int i = 0; i < NumberOfContexts; i++)
for (uptr i = 0; i < NumberOfContexts; i++)
ThreadContexts[i].init();
}

View File

@ -162,7 +162,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align, bool signal) {
}
void *user_calloc(ThreadState *thr, uptr pc, uptr size, uptr n) {
if (CallocShouldReturnNullDueToOverflow(size, n))
if (CheckForCallocOverflow(size, n))
return Allocator::FailureHandler::OnBadRequest();
void *p = user_alloc(thr, pc, n * size);
if (p)

View File

@ -12,6 +12,7 @@
// Interceptors for operators new and delete.
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "tsan_interceptors.h"
@ -24,13 +25,15 @@ struct nothrow_t {};
DECLARE_REAL(void *, malloc, uptr size)
DECLARE_REAL(void, free, void *ptr)
#define OPERATOR_NEW_BODY(mangled_name) \
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
#define OPERATOR_NEW_BODY(mangled_name, nothrow) \
if (cur_thread()->in_symbolizer) \
return InternalAlloc(size); \
void *p = 0; \
{ \
SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
p = user_alloc(thr, pc, size); \
if (!nothrow && UNLIKELY(!p)) DieOnFailure::OnOOM(); \
} \
invoke_malloc_hook(p, size); \
return p;
@ -38,25 +41,25 @@ DECLARE_REAL(void, free, void *ptr)
SANITIZER_INTERFACE_ATTRIBUTE
void *operator new(__sanitizer::uptr size);
void *operator new(__sanitizer::uptr size) {
OPERATOR_NEW_BODY(_Znwm);
OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/);
}
SANITIZER_INTERFACE_ATTRIBUTE
void *operator new[](__sanitizer::uptr size);
void *operator new[](__sanitizer::uptr size) {
OPERATOR_NEW_BODY(_Znam);
OPERATOR_NEW_BODY(_Znam, false /*nothrow*/);
}
SANITIZER_INTERFACE_ATTRIBUTE
void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/);
}
SANITIZER_INTERFACE_ATTRIBUTE
void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/);
}
#define OPERATOR_DELETE_BODY(mangled_name) \

View File

@ -0,0 +1,6 @@
# List of function matchers common to C/C++ applications that make sense to
# always instrument. You can use this as an argument to
# -fxray-always-instrument=<path> along with your project-specific lists.
# Always instrument the main function.
fun:main

View File

@ -0,0 +1,6 @@
# List of function matchers common to C/C++ applications that make sense to
# never instrument. You can use this as an argument to
# -fxray-never-instrument=<path> along with your project-specific lists.
# Never instrument any function whose symbol starts with __xray.
fun:__xray*

View File

@ -1176,11 +1176,6 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
#define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \
__attribute__((availability(macosx,strict,introduced=10.9))) \
__attribute__((availability(ios,strict,introduced=7.0)))
#define _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION \
__attribute__((availability(macosx,strict,introduced=10.13))) \
__attribute__((availability(ios,strict,introduced=11.0))) \
__attribute__((availability(tvos,strict,introduced=11.0))) \
__attribute__((availability(watchos,strict,introduced=4.0)))
#else
#define _LIBCPP_AVAILABILITY_SHARED_MUTEX
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
@ -1192,7 +1187,6 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
#define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE
#define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY
#define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR
#define _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION
#endif
// Define availability that depends on _LIBCPP_NO_EXCEPTIONS.

View File

@ -193,20 +193,20 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE void operato
#endif
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void* operator new(std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void* operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void operator delete(void* __p, std::align_val_t) _NOEXCEPT;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void operator delete(void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
_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 _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION 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 _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void* operator new[](std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void* operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void operator delete[](void* __p, std::align_val_t) _NOEXCEPT;
_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION void operator delete[](void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
_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 _LIBCPP_AVAILABILITY_ALIGNED_ALLOCATION 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

View File

@ -4004,6 +4004,10 @@ basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator*
#endif // _LIBCPP_DEBUG_LEVEL >= 2
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<char>)
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<wchar_t>)
_LIBCPP_EXTERN_TEMPLATE(string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&))
#if _LIBCPP_STD_VER > 11
// Literal suffixes for basic_string [basic.string.literals]
inline namespace literals
@ -4037,10 +4041,6 @@ inline namespace literals
}
#endif
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<char>)
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_string<wchar_t>)
_LIBCPP_EXTERN_TEMPLATE(string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&))
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS

View File

@ -33,7 +33,7 @@ extern "C" {
* @{
*/
/** See llvm::createBBVectorizePass function. */
/** DEPRECATED - Use LLVMAddSLPVectorizePass */
void LLVMAddBBVectorizePass(LLVMPassManagerRef PM);
/** See llvm::createLoopVectorizePass function. */

View File

@ -69,10 +69,15 @@ class AliasSet : public ilist_node<AliasSet> {
if (AAInfo == DenseMapInfo<AAMDNodes>::getEmptyKey())
// We don't have a AAInfo yet. Set it to NewAAInfo.
AAInfo = NewAAInfo;
else if (AAInfo != NewAAInfo)
// NewAAInfo conflicts with AAInfo.
AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey();
else {
AAMDNodes Intersection(AAInfo.intersect(NewAAInfo));
if (!Intersection) {
// NewAAInfo conflicts with AAInfo.
AAInfo = DenseMapInfo<AAMDNodes>::getTombstoneKey();
return SizeChanged;
}
AAInfo = Intersection;
}
return SizeChanged;
}

View File

@ -0,0 +1,58 @@
//=- CFLAliasAnalysisUtils.h - Utilities for CFL Alias Analysis ----*- C++-*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// \file
// These are the utilities/helpers used by the CFL Alias Analyses available in
// tree, i.e. Steensgaard's and Andersens'.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H
#define LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
namespace llvm {
namespace cflaa {
template <typename AAResult> struct FunctionHandle final : public CallbackVH {
FunctionHandle(Function *Fn, AAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
}
void deleted() override { removeSelfFromCache(); }
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
AAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
auto *Val = getValPtr();
Result->evict(cast<Function>(Val));
setValPtr(nullptr);
}
};
static inline const Function *parentFunctionOfValue(const Value *Val) {
if (auto *Inst = dyn_cast<Instruction>(Val)) {
auto *Bb = Inst->getParent();
return Bb->getParent();
}
if (auto *Arg = dyn_cast<Argument>(Val))
return Arg->getParent();
return nullptr;
} // namespace cflaa
} // namespace llvm
}
#endif // LLVM_ANALYSIS_CFLALIASANALYSISUTILS_H

View File

@ -18,8 +18,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CFLAliasAnalysisUtils.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <forward_list>
@ -47,7 +47,7 @@ class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> {
return false;
}
/// Evict the given function from cache
void evict(const Function &Fn);
void evict(const Function *Fn);
/// \brief Get the alias summary for the given function
/// Return nullptr if the summary is not found or not available
@ -57,27 +57,6 @@ class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> {
AliasResult alias(const MemoryLocation &, const MemoryLocation &);
private:
struct FunctionHandle final : public CallbackVH {
FunctionHandle(Function *Fn, CFLAndersAAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
}
void deleted() override { removeSelfFromCache(); }
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
CFLAndersAAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
auto *Val = getValPtr();
Result->evict(*cast<Function>(Val));
setValPtr(nullptr);
}
};
/// \brief Ensures that the given function is available in the cache.
/// Returns the appropriate entry from the cache.
const Optional<FunctionInfo> &ensureCached(const Function &);
@ -97,7 +76,7 @@ class CFLAndersAAResult : public AAResultBase<CFLAndersAAResult> {
/// that simply has empty sets.
DenseMap<const Function *, Optional<FunctionInfo>> Cache;
std::forward_list<FunctionHandle> Handles;
std::forward_list<cflaa::FunctionHandle<CFLAndersAAResult>> Handles;
};
/// Analysis pass providing a never-invalidated alias analysis result.

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CFLAliasAnalysisUtils.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
@ -85,27 +86,6 @@ class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> {
}
private:
struct FunctionHandle final : public CallbackVH {
FunctionHandle(Function *Fn, CFLSteensAAResult *Result)
: CallbackVH(Fn), Result(Result) {
assert(Fn != nullptr);
assert(Result != nullptr);
}
void deleted() override { removeSelfFromCache(); }
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
private:
CFLSteensAAResult *Result;
void removeSelfFromCache() {
assert(Result != nullptr);
auto *Val = getValPtr();
Result->evict(cast<Function>(Val));
setValPtr(nullptr);
}
};
const TargetLibraryInfo &TLI;
/// \brief Cached mapping of Functions to their StratifiedSets.
@ -114,7 +94,7 @@ class CFLSteensAAResult : public AAResultBase<CFLSteensAAResult> {
/// have any kind of recursion, it is discernable from a function
/// that simply has empty sets.
DenseMap<Function *, Optional<FunctionInfo>> Cache;
std::forward_list<FunctionHandle> Handles;
std::forward_list<cflaa::FunctionHandle<CFLSteensAAResult>> Handles;
FunctionInfo buildSetsFrom(Function *F);
};

View File

@ -86,7 +86,6 @@ class IDFCalculator {
private:
DominatorTreeBase<BasicBlock> &DT;
bool useLiveIn;
DenseMap<DomTreeNode *, unsigned> DomLevels;
const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks;
const SmallPtrSetImpl<BasicBlock *> *DefBlocks;
};

View File

@ -139,7 +139,7 @@ class MemoryAccess
// Methods for support type inquiry through isa, cast, and
// dyn_cast
static inline bool classof(const Value *V) {
static bool classof(const Value *V) {
unsigned ID = V->getValueID();
return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
}
@ -241,7 +241,7 @@ class MemoryUseOrDef : public MemoryAccess {
/// \brief Get the access that produces the memory state used by this Use.
MemoryAccess *getDefiningAccess() const { return getOperand(0); }
static inline bool classof(const Value *MA) {
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal;
}
@ -297,7 +297,7 @@ class MemoryUse final : public MemoryUseOrDef {
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
static inline bool classof(const Value *MA) {
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal;
}
@ -353,7 +353,7 @@ class MemoryDef final : public MemoryUseOrDef {
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
static inline bool classof(const Value *MA) {
static bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
}
@ -526,7 +526,7 @@ class MemoryPhi final : public MemoryAccess {
return getIncomingValue(Idx);
}
static inline bool classof(const Value *V) {
static bool classof(const Value *V) {
return V->getValueID() == MemoryPhiVal;
}

View File

@ -34,7 +34,7 @@ class Value;
///
/// It allows reporting when optimizations are performed and when they are not
/// along with the reasons for it. Hotness information of the corresponding
/// code region can be included in the remark if DiagnosticHotnessRequested is
/// code region can be included in the remark if DiagnosticsHotnessRequested is
/// enabled in the LLVM context.
class OptimizationRemarkEmitter {
public:
@ -45,10 +45,10 @@ class OptimizationRemarkEmitter {
/// analysis pass).
///
/// Note that this ctor has a very different cost depending on whether
/// F->getContext().getDiagnosticHotnessRequested() is on or not. If it's off
/// F->getContext().getDiagnosticsHotnessRequested() is on or not. If it's off
/// the operation is free.
///
/// Whereas if DiagnosticHotnessRequested is on, it is fairly expensive
/// Whereas if DiagnosticsHotnessRequested is on, it is fairly expensive
/// operation since BFI and all its required analyses are computed. This is
/// for example useful for CGSCC passes that can't use function analyses
/// passes in the old PM.

View File

@ -37,18 +37,38 @@
#ifndef LLVM_ANALYSIS_REGIONINFO_H
#define LLVM_ANALYSIS_REGIONINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <type_traits>
#include <vector>
namespace llvm {
class DominanceFrontier;
class DominatorTree;
class Loop;
class LoopInfo;
struct PostDominatorTree;
class Region;
template <class RegionTr> class RegionBase;
class RegionInfo;
template <class RegionTr> class RegionInfoBase;
class RegionNode;
// Class to be specialized for different users of RegionInfo
// (i.e. BasicBlocks or MachineBasicBlocks). This is only to avoid needing to
// pass around an unreasonable number of template parameters.
@ -59,37 +79,23 @@ struct RegionTraits {
// RegionT
// RegionNodeT
// RegionInfoT
typedef typename FuncT_::UnknownRegionTypeError BrokenT;
using BrokenT = typename FuncT_::UnknownRegionTypeError;
};
class DominatorTree;
class DominanceFrontier;
class Loop;
class LoopInfo;
struct PostDominatorTree;
class raw_ostream;
class Region;
template <class RegionTr>
class RegionBase;
class RegionNode;
class RegionInfo;
template <class RegionTr>
class RegionInfoBase;
template <>
struct RegionTraits<Function> {
typedef Function FuncT;
typedef BasicBlock BlockT;
typedef Region RegionT;
typedef RegionNode RegionNodeT;
typedef RegionInfo RegionInfoT;
typedef DominatorTree DomTreeT;
typedef DomTreeNode DomTreeNodeT;
typedef DominanceFrontier DomFrontierT;
typedef PostDominatorTree PostDomTreeT;
typedef Instruction InstT;
typedef Loop LoopT;
typedef LoopInfo LoopInfoT;
using FuncT = Function;
using BlockT = BasicBlock;
using RegionT = Region;
using RegionNodeT = RegionNode;
using RegionInfoT = RegionInfo;
using DomTreeT = DominatorTree;
using DomTreeNodeT = DomTreeNode;
using DomFrontierT = DominanceFrontier;
using PostDomTreeT = PostDominatorTree;
using InstT = Instruction;
using LoopT = Loop;
using LoopInfoT = LoopInfo;
static unsigned getNumSuccessors(BasicBlock *BB) {
return BB->getTerminator()->getNumSuccessors();
@ -113,13 +119,10 @@ class RegionNodeBase {
friend class RegionBase<Tr>;
public:
typedef typename Tr::BlockT BlockT;
typedef typename Tr::RegionT RegionT;
using BlockT = typename Tr::BlockT;
using RegionT = typename Tr::RegionT;
private:
RegionNodeBase(const RegionNodeBase &) = delete;
const RegionNodeBase &operator=(const RegionNodeBase &) = delete;
/// This is the entry basic block that starts this region node. If this is a
/// BasicBlock RegionNode, then entry is just the basic block, that this
/// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode.
@ -150,6 +153,9 @@ class RegionNodeBase {
: entry(Entry, isSubRegion), parent(Parent) {}
public:
RegionNodeBase(const RegionNodeBase &) = delete;
RegionNodeBase &operator=(const RegionNodeBase &) = delete;
/// @brief Get the parent Region of this RegionNode.
///
/// The parent Region is the Region this RegionNode belongs to. If for
@ -247,24 +253,22 @@ class RegionNodeBase {
/// tree, the second one creates a graphical representation using graphviz.
template <class Tr>
class RegionBase : public RegionNodeBase<Tr> {
typedef typename Tr::FuncT FuncT;
typedef typename Tr::BlockT BlockT;
typedef typename Tr::RegionInfoT RegionInfoT;
typedef typename Tr::RegionT RegionT;
typedef typename Tr::RegionNodeT RegionNodeT;
typedef typename Tr::DomTreeT DomTreeT;
typedef typename Tr::LoopT LoopT;
typedef typename Tr::LoopInfoT LoopInfoT;
typedef typename Tr::InstT InstT;
typedef GraphTraits<BlockT *> BlockTraits;
typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits;
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
typedef typename InvBlockTraits::ChildIteratorType PredIterTy;
friend class RegionInfoBase<Tr>;
RegionBase(const RegionBase &) = delete;
const RegionBase &operator=(const RegionBase &) = delete;
using FuncT = typename Tr::FuncT;
using BlockT = typename Tr::BlockT;
using RegionInfoT = typename Tr::RegionInfoT;
using RegionT = typename Tr::RegionT;
using RegionNodeT = typename Tr::RegionNodeT;
using DomTreeT = typename Tr::DomTreeT;
using LoopT = typename Tr::LoopT;
using LoopInfoT = typename Tr::LoopInfoT;
using InstT = typename Tr::InstT;
using BlockTraits = GraphTraits<BlockT *>;
using InvBlockTraits = GraphTraits<Inverse<BlockT *>>;
using SuccIterTy = typename BlockTraits::ChildIteratorType;
using PredIterTy = typename InvBlockTraits::ChildIteratorType;
// Information necessary to manage this Region.
RegionInfoT *RI;
@ -274,12 +278,12 @@ class RegionBase : public RegionNodeBase<Tr> {
// (The entry BasicBlock is part of RegionNode)
BlockT *exit;
typedef std::vector<std::unique_ptr<RegionT>> RegionSet;
using RegionSet = std::vector<std::unique_ptr<RegionT>>;
// The subregions of this region.
RegionSet children;
typedef std::map<BlockT *, std::unique_ptr<RegionNodeT>> BBNodeMapT;
using BBNodeMapT = std::map<BlockT *, std::unique_ptr<RegionNodeT>>;
// Save the BasicBlock RegionNodes that are element of this Region.
mutable BBNodeMapT BBNodeMap;
@ -308,6 +312,9 @@ class RegionBase : public RegionNodeBase<Tr> {
RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT,
RegionT *Parent = nullptr);
RegionBase(const RegionBase &) = delete;
RegionBase &operator=(const RegionBase &) = delete;
/// Delete the Region and all its subregions.
~RegionBase();
@ -543,8 +550,8 @@ class RegionBase : public RegionNodeBase<Tr> {
///
/// These iterators iterator over all subregions of this Region.
//@{
typedef typename RegionSet::iterator iterator;
typedef typename RegionSet::const_iterator const_iterator;
using iterator = typename RegionSet::iterator;
using const_iterator = typename RegionSet::const_iterator;
iterator begin() { return children.begin(); }
iterator end() { return children.end(); }
@ -563,12 +570,13 @@ class RegionBase : public RegionNodeBase<Tr> {
class block_iterator_wrapper
: public df_iterator<
typename std::conditional<IsConst, const BlockT, BlockT>::type *> {
typedef df_iterator<
typename std::conditional<IsConst, const BlockT, BlockT>::type *> super;
using super =
df_iterator<
typename std::conditional<IsConst, const BlockT, BlockT>::type *>;
public:
typedef block_iterator_wrapper<IsConst> Self;
typedef typename super::value_type value_type;
using Self = block_iterator_wrapper<IsConst>;
using value_type = typename super::value_type;
// Construct the begin iterator.
block_iterator_wrapper(value_type Entry, value_type Exit)
@ -592,8 +600,8 @@ class RegionBase : public RegionNodeBase<Tr> {
}
};
typedef block_iterator_wrapper<false> block_iterator;
typedef block_iterator_wrapper<true> const_block_iterator;
using block_iterator = block_iterator_wrapper<false>;
using const_block_iterator = block_iterator_wrapper<true>;
block_iterator block_begin() { return block_iterator(getEntry(), getExit()); }
@ -604,8 +612,8 @@ class RegionBase : public RegionNodeBase<Tr> {
}
const_block_iterator block_end() const { return const_block_iterator(); }
typedef iterator_range<block_iterator> block_range;
typedef iterator_range<const_block_iterator> const_block_range;
using block_range = iterator_range<block_iterator>;
using const_block_range = iterator_range<const_block_iterator>;
/// @brief Returns a range view of the basic blocks in the region.
inline block_range blocks() {
@ -626,14 +634,14 @@ class RegionBase : public RegionNodeBase<Tr> {
/// are direct children of this Region. It does not iterate over any
/// RegionNodes that are also element of a subregion of this Region.
//@{
typedef df_iterator<RegionNodeT *, df_iterator_default_set<RegionNodeT *>,
false, GraphTraits<RegionNodeT *>>
element_iterator;
using element_iterator =
df_iterator<RegionNodeT *, df_iterator_default_set<RegionNodeT *>, false,
GraphTraits<RegionNodeT *>>;
typedef df_iterator<const RegionNodeT *,
df_iterator_default_set<const RegionNodeT *>, false,
GraphTraits<const RegionNodeT *>>
const_element_iterator;
using const_element_iterator =
df_iterator<const RegionNodeT *,
df_iterator_default_set<const RegionNodeT *>, false,
GraphTraits<const RegionNodeT *>>;
element_iterator element_begin();
element_iterator element_end();
@ -661,29 +669,26 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node);
/// Tree.
template <class Tr>
class RegionInfoBase {
typedef typename Tr::BlockT BlockT;
typedef typename Tr::FuncT FuncT;
typedef typename Tr::RegionT RegionT;
typedef typename Tr::RegionInfoT RegionInfoT;
typedef typename Tr::DomTreeT DomTreeT;
typedef typename Tr::DomTreeNodeT DomTreeNodeT;
typedef typename Tr::PostDomTreeT PostDomTreeT;
typedef typename Tr::DomFrontierT DomFrontierT;
typedef GraphTraits<BlockT *> BlockTraits;
typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits;
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
typedef typename InvBlockTraits::ChildIteratorType PredIterTy;
friend class RegionInfo;
friend class MachineRegionInfo;
typedef DenseMap<BlockT *, BlockT *> BBtoBBMap;
typedef DenseMap<BlockT *, RegionT *> BBtoRegionMap;
using BlockT = typename Tr::BlockT;
using FuncT = typename Tr::FuncT;
using RegionT = typename Tr::RegionT;
using RegionInfoT = typename Tr::RegionInfoT;
using DomTreeT = typename Tr::DomTreeT;
using DomTreeNodeT = typename Tr::DomTreeNodeT;
using PostDomTreeT = typename Tr::PostDomTreeT;
using DomFrontierT = typename Tr::DomFrontierT;
using BlockTraits = GraphTraits<BlockT *>;
using InvBlockTraits = GraphTraits<Inverse<BlockT *>>;
using SuccIterTy = typename BlockTraits::ChildIteratorType;
using PredIterTy = typename InvBlockTraits::ChildIteratorType;
using BBtoBBMap = DenseMap<BlockT *, BlockT *>;
using BBtoRegionMap = DenseMap<BlockT *, RegionT *>;
RegionInfoBase();
virtual ~RegionInfoBase();
RegionInfoBase(const RegionInfoBase &) = delete;
const RegionInfoBase &operator=(const RegionInfoBase &) = delete;
RegionInfoBase(RegionInfoBase &&Arg)
: DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)),
@ -691,6 +696,7 @@ class RegionInfoBase {
BBtoRegion(std::move(Arg.BBtoRegion)) {
Arg.wipe();
}
RegionInfoBase &operator=(RegionInfoBase &&RHS) {
DT = std::move(RHS.DT);
PDT = std::move(RHS.PDT);
@ -701,12 +707,14 @@ class RegionInfoBase {
return *this;
}
virtual ~RegionInfoBase();
DomTreeT *DT;
PostDomTreeT *PDT;
DomFrontierT *DF;
/// The top level region.
RegionT *TopLevelRegion;
RegionT *TopLevelRegion = nullptr;
/// Map every BB to the smallest region, that contains BB.
BBtoRegionMap BBtoRegion;
@ -785,6 +793,9 @@ class RegionInfoBase {
void calculate(FuncT &F);
public:
RegionInfoBase(const RegionInfoBase &) = delete;
RegionInfoBase &operator=(const RegionInfoBase &) = delete;
static bool VerifyRegionInfo;
static typename RegionT::PrintStyle printStyle;
@ -887,21 +898,22 @@ class Region : public RegionBase<RegionTraits<Function>> {
class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
typedef RegionInfoBase<RegionTraits<Function>> Base;
using Base = RegionInfoBase<RegionTraits<Function>>;
explicit RegionInfo();
~RegionInfo() override;
RegionInfo(RegionInfo &&Arg) : Base(std::move(static_cast<Base &>(Arg))) {
updateRegionTree(*this, TopLevelRegion);
}
RegionInfo &operator=(RegionInfo &&RHS) {
Base::operator=(std::move(static_cast<Base &>(RHS)));
updateRegionTree(*this, TopLevelRegion);
return *this;
}
~RegionInfo() override;
/// Handle invalidation explicitly.
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &);
@ -931,8 +943,8 @@ class RegionInfoPass : public FunctionPass {
public:
static char ID;
explicit RegionInfoPass();
explicit RegionInfoPass();
~RegionInfoPass() override;
RegionInfo &getRegionInfo() { return RI; }
@ -953,10 +965,11 @@ class RegionInfoPass : public FunctionPass {
/// \brief Analysis pass that exposes the \c RegionInfo for a function.
class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> {
friend AnalysisInfoMixin<RegionInfoAnalysis>;
static AnalysisKey Key;
public:
typedef RegionInfo Result;
using Result = RegionInfo;
RegionInfo run(Function &F, FunctionAnalysisManager &AM);
};
@ -967,6 +980,7 @@ class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> {
public:
explicit RegionInfoPrinterPass(raw_ostream &OS);
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
@ -995,8 +1009,8 @@ RegionNodeBase<RegionTraits<Function>>::getNodeAs<Region>() const {
template <class Tr>
inline raw_ostream &operator<<(raw_ostream &OS,
const RegionNodeBase<Tr> &Node) {
typedef typename Tr::BlockT BlockT;
typedef typename Tr::RegionT RegionT;
using BlockT = typename Tr::BlockT;
using RegionT = typename Tr::RegionT;
if (Node.isSubRegion())
return OS << Node.template getNodeAs<RegionT>()->getNameStr();
@ -1008,5 +1022,6 @@ extern template class RegionBase<RegionTraits<Function>>;
extern template class RegionNodeBase<RegionTraits<Function>>;
extern template class RegionInfoBase<RegionTraits<Function>>;
} // End llvm namespace
#endif
} // end namespace llvm
#endif // LLVM_ANALYSIS_REGIONINFO_H

View File

@ -12,7 +12,11 @@
#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H
#define LLVM_ANALYSIS_REGIONINFOIMPL_H
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/PostDominators.h"
@ -20,9 +24,15 @@
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <memory>
#include <set>
#include <string>
#include <type_traits>
#include <vector>
namespace llvm {
@ -303,7 +313,8 @@ RegionBase<Tr>::element_end() const {
template <class Tr>
typename Tr::RegionT *RegionBase<Tr>::getSubRegionNode(BlockT *BB) const {
typedef typename Tr::RegionT RegionT;
using RegionT = typename Tr::RegionT;
RegionT *R = RI->getRegionFor(BB);
if (!R || R == this)
@ -330,7 +341,8 @@ typename Tr::RegionNodeT *RegionBase<Tr>::getBBNode(BlockT *BB) const {
if (at == BBNodeMap.end()) {
auto Deconst = const_cast<RegionBase<Tr> *>(this);
typename BBNodeMapT::value_type V = {
BB, make_unique<RegionNodeT>(static_cast<RegionT *>(Deconst), BB)};
BB,
llvm::make_unique<RegionNodeT>(static_cast<RegionT *>(Deconst), BB)};
at = BBNodeMap.insert(std::move(V)).first;
}
return at->second.get();
@ -357,10 +369,10 @@ void RegionBase<Tr>::transferChildrenTo(RegionT *To) {
template <class Tr>
void RegionBase<Tr>::addSubRegion(RegionT *SubRegion, bool moveChildren) {
assert(!SubRegion->parent && "SubRegion already has a parent!");
assert(find_if(*this,
[&](const std::unique_ptr<RegionT> &R) {
return R.get() == SubRegion;
}) == children.end() &&
assert(llvm::find_if(*this,
[&](const std::unique_ptr<RegionT> &R) {
return R.get() == SubRegion;
}) == children.end() &&
"Subregion already exists!");
SubRegion->parent = static_cast<RegionT *>(this);
@ -402,7 +414,7 @@ typename Tr::RegionT *RegionBase<Tr>::removeSubRegion(RegionT *Child) {
assert(Child->parent == this && "Child is not a child of this region!");
Child->parent = nullptr;
typename RegionSet::iterator I =
find_if(children, [&](const std::unique_ptr<RegionT> &R) {
llvm::find_if(children, [&](const std::unique_ptr<RegionT> &R) {
return R.get() == Child;
});
assert(I != children.end() && "Region does not exit. Unable to remove.");
@ -505,8 +517,7 @@ void RegionBase<Tr>::clearNodeCache() {
//
template <class Tr>
RegionInfoBase<Tr>::RegionInfoBase()
: TopLevelRegion(nullptr) {}
RegionInfoBase<Tr>::RegionInfoBase() = default;
template <class Tr>
RegionInfoBase<Tr>::~RegionInfoBase() {
@ -543,7 +554,8 @@ bool RegionInfoBase<Tr>::isCommonDomFrontier(BlockT *BB, BlockT *entry,
template <class Tr>
bool RegionInfoBase<Tr>::isRegion(BlockT *entry, BlockT *exit) const {
assert(entry && exit && "entry and exit must not be null!");
typedef typename DomFrontierT::DomSetType DST;
using DST = typename DomFrontierT::DomSetType;
DST *entrySuccs = &DF->find(entry)->second;
@ -689,7 +701,8 @@ void RegionInfoBase<Tr>::findRegionsWithEntry(BlockT *entry,
template <class Tr>
void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {
typedef typename std::add_pointer<FuncT>::type FuncPtrT;
using FuncPtrT = typename std::add_pointer<FuncT>::type;
BlockT *entry = GraphTraits<FuncPtrT>::getEntryNode(&F);
DomTreeNodeT *N = DT->getNode(entry);
@ -876,7 +889,7 @@ RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const {
template <class Tr>
void RegionInfoBase<Tr>::calculate(FuncT &F) {
typedef typename std::add_pointer<FuncT>::type FuncPtrT;
using FuncPtrT = typename std::add_pointer<FuncT>::type;
// ShortCut a function where for every BB the exit of the largest region
// starting with BB is stored. These regions can be threated as single BBS.
@ -892,4 +905,4 @@ void RegionInfoBase<Tr>::calculate(FuncT &F) {
} // end namespace llvm
#endif
#endif // LLVM_ANALYSIS_REGIONINFOIMPL_H

View File

@ -8,17 +8,23 @@
//===----------------------------------------------------------------------===//
// This file defines the iterators to iterate over the elements of a Region.
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_REGIONITERATOR_H
#define LLVM_ANALYSIS_REGIONITERATOR_H
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/IR/CFG.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <iterator>
#include <type_traits>
namespace llvm {
class BasicBlock;
//===----------------------------------------------------------------------===//
/// @brief Hierarchical RegionNode successor iterator.
///
@ -33,10 +39,9 @@ namespace llvm {
template <class NodeRef, class BlockT, class RegionT>
class RNSuccIterator
: public std::iterator<std::forward_iterator_tag, NodeRef> {
typedef std::iterator<std::forward_iterator_tag, NodeRef> super;
typedef GraphTraits<BlockT*> BlockTraits;
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
using super = std::iterator<std::forward_iterator_tag, NodeRef>;
using BlockTraits = GraphTraits<BlockT *>;
using SuccIterTy = typename BlockTraits::ChildIteratorType;
// The iterator works in two modes, bb mode or region mode.
enum ItMode {
@ -92,16 +97,15 @@ class RNSuccIterator
inline bool isExit(BlockT* BB) const {
return getNode()->getParent()->getExit() == BB;
}
public:
typedef RNSuccIterator<NodeRef, BlockT, RegionT> Self;
typedef typename super::value_type value_type;
public:
using Self = RNSuccIterator<NodeRef, BlockT, RegionT>;
using value_type = typename super::value_type;
/// @brief Create begin iterator of a RegionNode.
inline RNSuccIterator(NodeRef node)
: Node(node, node->isSubRegion() ? ItRgBegin : ItBB),
BItor(BlockTraits::child_begin(node->getEntry())) {
// Skip the exit block
if (!isRegionMode())
while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor))
@ -153,7 +157,6 @@ class RNSuccIterator
}
};
//===----------------------------------------------------------------------===//
/// @brief Flat RegionNode iterator.
///
@ -163,16 +166,16 @@ class RNSuccIterator
template <class NodeRef, class BlockT, class RegionT>
class RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>
: public std::iterator<std::forward_iterator_tag, NodeRef> {
typedef std::iterator<std::forward_iterator_tag, NodeRef> super;
typedef GraphTraits<BlockT*> BlockTraits;
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
using super = std::iterator<std::forward_iterator_tag, NodeRef>;
using BlockTraits = GraphTraits<BlockT *>;
using SuccIterTy = typename BlockTraits::ChildIteratorType;
NodeRef Node;
SuccIterTy Itor;
public:
typedef RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT> Self;
typedef typename super::value_type value_type;
using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>;
using value_type = typename super::value_type;
/// @brief Create the iterator from a RegionNode.
///
@ -255,8 +258,8 @@ inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) {
#define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \
template <> struct GraphTraits<NodeT *> { \
typedef NodeT *NodeRef; \
typedef RNSuccIterator<NodeRef, BlockT, RegionT> ChildIteratorType; \
using NodeRef = NodeT *; \
using ChildIteratorType = RNSuccIterator<NodeRef, BlockT, RegionT>; \
static NodeRef getEntryNode(NodeRef N) { return N; } \
static inline ChildIteratorType child_begin(NodeRef N) { \
return RNSuccIterator<NodeRef, BlockT, RegionT>(N); \
@ -266,9 +269,9 @@ inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) {
} \
}; \
template <> struct GraphTraits<FlatIt<NodeT *>> { \
typedef NodeT *NodeRef; \
typedef RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT> \
ChildIteratorType; \
using NodeRef = NodeT *; \
using ChildIteratorType = \
RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>; \
static NodeRef getEntryNode(NodeRef N) { return N; } \
static inline ChildIteratorType child_begin(NodeRef N) { \
return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N); \
@ -280,7 +283,7 @@ inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) {
#define RegionGraphTraits(RegionT, NodeT) \
template <> struct GraphTraits<RegionT *> : public GraphTraits<NodeT *> { \
typedef df_iterator<NodeRef> nodes_iterator; \
using nodes_iterator = df_iterator<NodeRef>; \
static NodeRef getEntryNode(RegionT *R) { \
return R->getNode(R->getEntry()); \
} \
@ -294,9 +297,9 @@ inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) {
template <> \
struct GraphTraits<FlatIt<RegionT *>> \
: public GraphTraits<FlatIt<NodeT *>> { \
typedef df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, \
GraphTraits<FlatIt<NodeRef>>> \
nodes_iterator; \
using nodes_iterator = \
df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false, \
GraphTraits<FlatIt<NodeRef>>>; \
static NodeRef getEntryNode(RegionT *R) { \
return R->getBBNode(R->getEntry()); \
} \
@ -315,17 +318,19 @@ RegionGraphTraits(Region, RegionNode);
RegionGraphTraits(const Region, const RegionNode);
template <> struct GraphTraits<RegionInfo*>
: public GraphTraits<FlatIt<RegionNode*> > {
typedef df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
GraphTraits<FlatIt<NodeRef>>>
nodes_iterator;
: public GraphTraits<FlatIt<RegionNode*>> {
using nodes_iterator =
df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
GraphTraits<FlatIt<NodeRef>>>;
static NodeRef getEntryNode(RegionInfo *RI) {
return GraphTraits<FlatIt<Region*> >::getEntryNode(RI->getTopLevelRegion());
return GraphTraits<FlatIt<Region*>>::getEntryNode(RI->getTopLevelRegion());
}
static nodes_iterator nodes_begin(RegionInfo* RI) {
return nodes_iterator::begin(getEntryNode(RI));
}
static nodes_iterator nodes_end(RegionInfo *RI) {
return nodes_iterator::end(getEntryNode(RI));
}
@ -333,21 +338,23 @@ template <> struct GraphTraits<RegionInfo*>
template <> struct GraphTraits<RegionInfoPass*>
: public GraphTraits<RegionInfo *> {
typedef df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
GraphTraits<FlatIt<NodeRef>>>
nodes_iterator;
using nodes_iterator =
df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
GraphTraits<FlatIt<NodeRef>>>;
static NodeRef getEntryNode(RegionInfoPass *RI) {
return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo());
}
static nodes_iterator nodes_begin(RegionInfoPass* RI) {
return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo());
}
static nodes_iterator nodes_end(RegionInfoPass *RI) {
return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo());
}
};
} // End namespace llvm
} // end namespace llvm
#endif
#endif // LLVM_ANALYSIS_REGIONITERATOR_H

View File

@ -262,7 +262,7 @@ class SCEVEqualPredicate final : public SCEVPredicate {
const SCEVConstant *getRHS() const { return RHS; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVPredicate *P) {
static bool classof(const SCEVPredicate *P) {
return P->getKind() == P_Equal;
}
};
@ -360,7 +360,7 @@ class SCEVWrapPredicate final : public SCEVPredicate {
bool isAlwaysTrue() const override;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVPredicate *P) {
static bool classof(const SCEVPredicate *P) {
return P->getKind() == P_Wrap;
}
};
@ -406,7 +406,7 @@ class SCEVUnionPredicate final : public SCEVPredicate {
unsigned getComplexity() const override { return Preds.size(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVPredicate *P) {
static bool classof(const SCEVPredicate *P) {
return P->getKind() == P_Union;
}
};
@ -1197,20 +1197,8 @@ class ScalarEvolution {
const SCEV *getConstant(const APInt &Val);
const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty);
typedef SmallDenseMap<std::pair<const SCEV *, Type *>, const SCEV *, 8>
ExtendCacheTy;
const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getZeroExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getZeroExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getSignExtendExprCached(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getSignExtendExprImpl(const SCEV *Op, Type *Ty,
ExtendCacheTy &Cache);
const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,

View File

@ -46,7 +46,7 @@ namespace llvm {
Type *getType() const { return V->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scConstant;
}
};
@ -65,7 +65,7 @@ namespace llvm {
Type *getType() const { return Ty; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scTruncate ||
S->getSCEVType() == scZeroExtend ||
S->getSCEVType() == scSignExtend;
@ -82,7 +82,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scTruncate;
}
};
@ -97,7 +97,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scZeroExtend;
}
};
@ -112,7 +112,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scSignExtend;
}
};
@ -167,7 +167,7 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
S->getSCEVType() == scMulExpr ||
S->getSCEVType() == scSMaxExpr ||
@ -185,7 +185,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
S->getSCEVType() == scMulExpr ||
S->getSCEVType() == scSMaxExpr ||
@ -217,7 +217,7 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr;
}
};
@ -234,7 +234,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scMulExpr;
}
};
@ -263,7 +263,7 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scUDivExpr;
}
};
@ -345,7 +345,7 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scAddRecExpr;
}
};
@ -363,7 +363,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scSMaxExpr;
}
};
@ -382,7 +382,7 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scUMaxExpr;
}
};
@ -428,7 +428,7 @@ namespace llvm {
Type *getType() const { return getValPtr()->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEV *S) {
static bool classof(const SCEV *S) {
return S->getSCEVType() == scUnknown;
}
};

View File

@ -216,9 +216,23 @@ class TargetTransformInfo {
/// other context they may not be folded. This routine can distinguish such
/// cases.
///
/// \p Operands is a list of operands which can be a result of transformations
/// of the current operands. The number of the operands on the list must equal
/// to the number of the current operands the IR user has. Their order on the
/// list must be the same as the order of the current operands the IR user
/// has.
///
/// The returned cost is defined in terms of \c TargetCostConstants, see its
/// comments for a detailed explanation of the cost values.
int getUserCost(const User *U) const;
int getUserCost(const User *U, ArrayRef<const Value *> Operands) const;
/// \brief This is a helper function which calls the two-argument getUserCost
/// with \p Operands which are the current operands U has.
int getUserCost(const User *U) const {
SmallVector<const Value *, 4> Operands(U->value_op_begin(),
U->value_op_end());
return getUserCost(U, Operands);
}
/// \brief Return true if branch divergence exists.
///
@ -366,7 +380,8 @@ class TargetTransformInfo {
/// \brief Get target-customized preferences for the generic loop unrolling
/// transformation. The caller will initialize UP with the current
/// target-independent defaults.
void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
void getUnrollingPreferences(Loop *L, ScalarEvolution &,
UnrollingPreferences &UP) const;
/// @}
@ -823,13 +838,15 @@ class TargetTransformInfo::Concept {
ArrayRef<const Value *> Arguments) = 0;
virtual unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI,
unsigned &JTSize) = 0;
virtual int getUserCost(const User *U) = 0;
virtual int
getUserCost(const User *U, ArrayRef<const Value *> Operands) = 0;
virtual bool hasBranchDivergence() = 0;
virtual bool isSourceOfDivergence(const Value *V) = 0;
virtual bool isAlwaysUniform(const Value *V) = 0;
virtual unsigned getFlatAddressSpace() = 0;
virtual bool isLoweredToCall(const Function *F) = 0;
virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
virtual void getUnrollingPreferences(Loop *L, ScalarEvolution &,
UnrollingPreferences &UP) = 0;
virtual bool isLegalAddImmediate(int64_t Imm) = 0;
virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
@ -998,7 +1015,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
ArrayRef<const Value *> Arguments) override {
return Impl.getIntrinsicCost(IID, RetTy, Arguments);
}
int getUserCost(const User *U) override { return Impl.getUserCost(U); }
int getUserCost(const User *U, ArrayRef<const Value *> Operands) override {
return Impl.getUserCost(U, Operands);
}
bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); }
bool isSourceOfDivergence(const Value *V) override {
return Impl.isSourceOfDivergence(V);
@ -1015,8 +1034,9 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
bool isLoweredToCall(const Function *F) override {
return Impl.isLoweredToCall(F);
}
void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override {
return Impl.getUnrollingPreferences(L, UP);
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
UnrollingPreferences &UP) override {
return Impl.getUnrollingPreferences(L, SE, UP);
}
bool isLegalAddImmediate(int64_t Imm) override {
return Impl.isLegalAddImmediate(Imm);

View File

@ -217,7 +217,8 @@ class TargetTransformInfoImplBase {
return true;
}
void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {}
void getUnrollingPreferences(Loop *, ScalarEvolution &,
TTI::UnrollingPreferences &) {}
bool isLegalAddImmediate(int64_t Imm) { return false; }
@ -684,14 +685,14 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase {
return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys);
}
unsigned getUserCost(const User *U) {
unsigned getUserCost(const User *U, ArrayRef<const Value *> Operands) {
if (isa<PHINode>(U))
return TTI::TCC_Free; // Model all PHI nodes as free.
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
SmallVector<Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end());
return static_cast<T *>(this)->getGEPCost(
GEP->getSourceElementType(), GEP->getPointerOperand(), Indices);
return static_cast<T *>(this)->getGEPCost(GEP->getSourceElementType(),
GEP->getPointerOperand(),
Operands.drop_front());
}
if (auto CS = ImmutableCallSite(U)) {

View File

@ -382,7 +382,7 @@ enum RelocationTypesARM64 {
IMAGE_REL_ARM64_ADDR32 = 0x0001,
IMAGE_REL_ARM64_ADDR32NB = 0x0002,
IMAGE_REL_ARM64_BRANCH26 = 0x0003,
IMAGE_REL_ARM64_PAGEBASE_REL2 = 0x0004,
IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004,
IMAGE_REL_ARM64_REL21 = 0x0005,
IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006,
IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007,

View File

@ -62,6 +62,9 @@ enum LLVMConstants : uint32_t {
const uint32_t DW_CIE_ID = UINT32_MAX;
const uint64_t DW64_CIE_ID = UINT64_MAX;
// Identifier of an invalid DIE offset in the .debug_info section.
const uint32_t DW_INVALID_OFFSET = UINT32_MAX;
enum Tag : uint16_t {
#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR) DW_TAG_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"

View File

@ -112,6 +112,11 @@ struct WasmRelocation {
int64_t Addend; // A value to add to the symbol.
};
struct WasmLinkingData {
uint32_t DataSize;
uint32_t DataAlignment;
};
enum : unsigned {
WASM_SEC_CUSTOM = 0, // Custom / User-defined section
WASM_SEC_TYPE = 1, // Function signature declarations
@ -175,8 +180,10 @@ enum class ValType {
// Linking metadata kinds.
enum : unsigned {
WASM_STACK_POINTER = 0x1,
WASM_SYMBOL_INFO = 0x2,
WASM_STACK_POINTER = 0x1,
WASM_SYMBOL_INFO = 0x2,
WASM_DATA_SIZE = 0x3,
WASM_DATA_ALIGNMENT = 0x4,
};
enum : unsigned {

View File

@ -111,9 +111,14 @@ namespace llvm {
struct BitcodeFileContents {
std::vector<BitcodeModule> Mods;
StringRef Symtab, StrtabForSymtab;
};
/// Returns the contents of a bitcode file.
/// Returns the contents of a bitcode file. This includes the raw contents of
/// the symbol table embedded in the bitcode file. Clients which require a
/// symbol table should prefer to use irsymtab::read instead of this function
/// because it creates a reader for the irsymtab and handles upgrading bitcode
/// files without a symbol table or with an old symbol table.
Expected<BitcodeFileContents> getBitcodeFileContents(MemoryBufferRef Buffer);
/// Returns a list of modules in the specified bitcode buffer.

View File

@ -28,18 +28,34 @@ namespace llvm {
std::unique_ptr<BitstreamWriter> Stream;
StringTableBuilder StrtabBuilder{StringTableBuilder::RAW};
bool WroteStrtab = false;
// Owns any strings created by the irsymtab writer until we create the
// string table.
BumpPtrAllocator Alloc;
bool WroteStrtab = false, WroteSymtab = false;
void writeBlob(unsigned Block, unsigned Record, StringRef Blob);
std::vector<Module *> Mods;
public:
/// Create a BitcodeWriter that writes to Buffer.
BitcodeWriter(SmallVectorImpl<char> &Buffer);
~BitcodeWriter();
/// Attempt to write a symbol table to the bitcode file. This must be called
/// at most once after all modules have been written.
///
/// A reader does not require a symbol table to interpret a bitcode file;
/// the symbol table is needed only to improve link-time performance. So
/// this function may decide not to write a symbol table. It may so decide
/// if, for example, the target is unregistered or the IR is malformed.
void writeSymtab();
/// Write the bitcode file's string table. This must be called exactly once
/// after all modules have been written.
/// after all modules and the optional symbol table have been written.
void writeStrtab();
/// Copy the string table for another module into this bitcode file. This

View File

@ -22,7 +22,7 @@
namespace llvm {
namespace bitc {
// The only top-level block types are MODULE, IDENTIFICATION and STRTAB.
// The only top-level block types are MODULE, IDENTIFICATION, STRTAB and SYMTAB.
enum BlockIDs {
// Blocks
MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID,
@ -57,6 +57,8 @@ enum BlockIDs {
STRTAB_BLOCK_ID,
FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID,
SYMTAB_BLOCK_ID,
};
/// Identification block contains a string that describes the producer details,
@ -571,6 +573,10 @@ enum StrtabCodes {
STRTAB_BLOB = 1,
};
enum SymtabCodes {
SYMTAB_BLOB = 1,
};
} // End bitc namespace
} // End llvm namespace

View File

@ -277,7 +277,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
unsigned getInliningThresholdMultiplier() { return 1; }
void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) {
void getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
TTI::UnrollingPreferences &UP) {
// This unrolling functionality is target independent, but to provide some
// motivation for its intended use, for x86:

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering --*- C++ -*-===//
//===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -15,21 +15,31 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
#define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetCallingConv.h"
#include <cstdint>
#include <functional>
namespace llvm {
// Forward declarations.
class DataLayout;
class Function;
class MachineIRBuilder;
class MachineOperand;
struct MachinePointerInfo;
class MachineRegisterInfo;
class TargetLowering;
class Type;
class Value;
class CallLowering {
const TargetLowering *TLI;
public:
struct ArgInfo {
unsigned Reg;
@ -49,6 +59,12 @@ class CallLowering {
/// arugment should go, exactly what happens can vary slightly. This
/// class abstracts the differences.
struct ValueHandler {
ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
CCAssignFn *AssignFn)
: MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {}
virtual ~ValueHandler() = default;
/// Materialize a VReg containing the address of the specified
/// stack-based object. This is either based on a FrameIndex or
/// direct SP manipulation, depending on the context. \p MPO
@ -89,12 +105,6 @@ class CallLowering {
return AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
}
ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
CCAssignFn *AssignFn)
: MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {}
virtual ~ValueHandler() {}
MachineIRBuilder &MIRBuilder;
MachineRegisterInfo &MRI;
CCAssignFn *AssignFn;
@ -112,7 +122,6 @@ class CallLowering {
return static_cast<const XXXTargetLowering *>(TLI);
}
template <typename FuncInfoTy>
void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
const FuncInfoTy &FuncInfo) const;
@ -126,7 +135,7 @@ class CallLowering {
public:
CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
virtual ~CallLowering() {}
virtual ~CallLowering() = default;
/// This hook must be implemented to lower outgoing return values, described
/// by \p Val, into the specified virtual register \p VReg.
@ -200,6 +209,7 @@ class CallLowering {
unsigned ResReg, ArrayRef<unsigned> ArgRegs,
std::function<unsigned()> GetCalleeReg) const;
};
} // End namespace llvm.
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ---*- C++ -*-===//
//===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -19,24 +19,33 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
#define LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H
#include "Types.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Types.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/IR/Intrinsics.h"
#include <memory>
#include <utility>
namespace llvm {
// Forward declarations.
class AllocaInst;
class BasicBlock;
class CallInst;
class CallLowering;
class Constant;
class DataLayout;
class Instruction;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class OptimizationRemarkEmitter;
class MachineRegisterInfo;
class OptimizationRemarkEmitter;
class PHINode;
class TargetPassConfig;
class User;
class Value;
// Technically the pass should run on an hypothetical MachineModule,
// since it should translate Global into some sort of MachineGlobal.
@ -53,6 +62,7 @@ class IRTranslator : public MachineFunctionPass {
private:
/// Interface used to lower the everything related to calls.
const CallLowering *CLI;
/// Mapping of the values of the current LLVM IR function
/// to the related virtual registers.
ValueToVReg ValToVReg;
@ -67,7 +77,7 @@ class IRTranslator : public MachineFunctionPass {
// a mapping between the edges arriving at the BasicBlock to the corresponding
// created MachineBasicBlocks. Some BasicBlocks that get translated to a
// single MachineBasicBlock may also end up in this Map.
typedef std::pair<const BasicBlock *, const BasicBlock *> CFGEdge;
using CFGEdge = std::pair<const BasicBlock *, const BasicBlock *>;
DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds;
// List of stubbed PHI instructions, for values and basic blocks to be filled
@ -165,7 +175,6 @@ class IRTranslator : public MachineFunctionPass {
return translateCompare(U, MIRBuilder);
}
/// Add remaining operands onto phis we've translated. Executed after all
/// MachineBasicBlocks for the function have been created.
void finishPendingPhis();
@ -356,7 +365,7 @@ class IRTranslator : public MachineFunctionPass {
MachineFunction *MF;
/// MachineRegisterInfo used to create virtual registers.
MachineRegisterInfo *MRI;
MachineRegisterInfo *MRI = nullptr;
const DataLayout *DL;
@ -430,5 +439,6 @@ class IRTranslator : public MachineFunctionPass {
bool runOnMachineFunction(MachineFunction &MF) override;
};
} // End namespace llvm.
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_IRTRANSLATOR_H

View File

@ -1,4 +1,4 @@
//==-- llvm/CodeGen/GlobalISel/InstructionSelector.h -------------*- C++ -*-==//
//===- llvm/CodeGen/GlobalISel/InstructionSelector.h ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -16,15 +16,16 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#include "llvm/ADT/Optional.h"
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
namespace llvm {
class MachineInstr;
class MachineInstrBuilder;
class MachineFunction;
class MachineOperand;
class MachineRegisterInfo;
class RegisterBankInfo;
@ -60,7 +61,7 @@ class PredicateBitsetImpl : public std::bitset<MaxPredicates> {
/// Provides the logic to select generic machine instructions.
class InstructionSelector {
public:
virtual ~InstructionSelector() {}
virtual ~InstructionSelector() = default;
/// Select the (possibly generic) instruction \p I to only use target-specific
/// opcodes. It is OK to insert multiple instructions, but they cannot be
@ -76,7 +77,7 @@ class InstructionSelector {
virtual bool select(MachineInstr &I) const = 0;
protected:
typedef std::function<void(MachineInstrBuilder &)> ComplexRendererFn;
using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>;
InstructionSelector();
@ -110,6 +111,6 @@ class InstructionSelector {
bool isObviouslySafeToFold(MachineInstr &MI) const;
};
} // End namespace llvm.
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H

View File

@ -1,4 +1,4 @@
//==-- llvm/CodeGen/GlobalISel/LegalizerInfo.h -------------------*- C++ -*-==//
//===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -12,33 +12,36 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZER_H
#define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZER_H
#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
#define LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/LowLevelTypeImpl.h"
#include "llvm/Target/TargetOpcodes.h"
#include <cstdint>
#include <functional>
#include <cassert>
#include <tuple>
#include <utility>
namespace llvm {
class LLVMContext;
class MachineInstr;
class MachineIRBuilder;
class MachineRegisterInfo;
class Type;
class VectorType;
/// Legalization is decided based on an instruction's opcode, which type slot
/// we're considering, and what the existing type is. These aspects are gathered
/// together for convenience in the InstrAspect class.
struct InstrAspect {
unsigned Opcode;
unsigned Idx;
unsigned Idx = 0;
LLT Type;
InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Idx(0), Type(Type) {}
InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
: Opcode(Opcode), Idx(Idx), Type(Type) {}
@ -104,6 +107,19 @@ class LegalizerInfo {
/// before any query is made or incorrect results may be returned.
void computeTables();
static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
switch (Action) {
case NarrowScalar:
case WidenScalar:
case FewerElements:
case MoreElements:
case Unsupported:
return true;
default:
return false;
}
}
/// More friendly way to set an action for common types that have an LLT
/// representation.
void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
@ -125,7 +141,6 @@ class LegalizerInfo {
ScalarInVectorActions[std::make_pair(Opcode, ScalarTy)] = Action;
}
/// Determine what action should be taken to legalize the given generic
/// instruction opcode, type-index and type. Requires computeTables to have
/// been called.
@ -145,8 +160,8 @@ class LegalizerInfo {
/// Iterate the given function (typically something like doubling the width)
/// on Ty until we find a legal type for this operation.
Optional<LLT> findLegalType(const InstrAspect &Aspect,
function_ref<LLT(LLT)> NextType) const {
Optional<LLT> findLegalizableSize(const InstrAspect &Aspect,
function_ref<LLT(LLT)> NextType) const {
LegalizeAction Action;
const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];
LLT Ty = Aspect.Type;
@ -158,10 +173,9 @@ class LegalizerInfo {
if (DefaultIt == DefaultActions.end())
return None;
Action = DefaultIt->second;
}
else
} else
Action = ActionIt->second;
} while(Action != Legal);
} while (needsLegalizingToDifferentSize(Action));
return Ty;
}
@ -203,18 +217,17 @@ class LegalizerInfo {
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
typedef DenseMap<LLT, LegalizeAction> TypeMap;
typedef DenseMap<std::pair<unsigned, LLT>, LegalizeAction> SIVActionMap;
using TypeMap = DenseMap<LLT, LegalizeAction>;
using SIVActionMap = DenseMap<std::pair<unsigned, LLT>, LegalizeAction>;
SmallVector<TypeMap, 1> Actions[LastOp - FirstOp + 1];
SIVActionMap ScalarInVectorActions;
DenseMap<std::pair<unsigned, LLT>, uint16_t> MaxLegalVectorElts;
DenseMap<unsigned, LegalizeAction> DefaultActions;
bool TablesInitialized;
bool TablesInitialized = false;
};
} // end namespace llvm
} // End namespace llvm.
#endif
#endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H

View File

@ -1,4 +1,4 @@
//== llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector -*- C++ -*-==//
//=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
@ -64,20 +64,27 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
#define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include <cassert>
#include <cstdint>
#include <memory>
namespace llvm {
// Forward declarations.
class BlockFrequency;
class MachineBranchProbabilityInfo;
class MachineBlockFrequencyInfo;
class MachineBranchProbabilityInfo;
class MachineOperand;
class MachineRegisterInfo;
class Pass;
class raw_ostream;
class TargetPassConfig;
class TargetRegisterInfo;
class raw_ostream;
/// This pass implements the reg bank selector pass used in the GlobalISel
/// pipeline. At the end of this pass, all register operands have been assigned
@ -105,6 +112,7 @@ class RegBankSelect : public MachineFunctionPass {
protected:
/// Tell if the insert point has already been materialized.
bool WasMaterialized = false;
/// Materialize the insertion point.
///
/// If isSplit() is true, this involves actually splitting
@ -128,7 +136,7 @@ class RegBankSelect : public MachineFunctionPass {
virtual MachineBasicBlock::iterator getPointImpl() = 0;
public:
virtual ~InsertPoint() {}
virtual ~InsertPoint() = default;
/// The first call to this method will cause the splitting to
/// happen if need be, then sub sequent calls just return
@ -197,6 +205,7 @@ class RegBankSelect : public MachineFunctionPass {
private:
/// Insertion point.
MachineInstr &Instr;
/// Does the insertion point is before or after Instr.
bool Before;
@ -216,6 +225,7 @@ class RegBankSelect : public MachineFunctionPass {
public:
/// Create an insertion point before (\p Before=true) or after \p Instr.
InstrInsertPoint(MachineInstr &Instr, bool Before = true);
bool isSplit() const override;
uint64_t frequency(const Pass &P) const override;
@ -228,6 +238,7 @@ class RegBankSelect : public MachineFunctionPass {
private:
/// Insertion point.
MachineBasicBlock &MBB;
/// Does the insertion point is at the beginning or end of MBB.
bool Beginning;
@ -252,6 +263,7 @@ class RegBankSelect : public MachineFunctionPass {
assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
"Invalid end point");
}
bool isSplit() const override { return false; }
uint64_t frequency(const Pass &P) const override;
bool canMaterialize() const override { return true; };
@ -262,10 +274,12 @@ class RegBankSelect : public MachineFunctionPass {
private:
/// Source of the edge.
MachineBasicBlock &Src;
/// Destination of the edge.
/// After the materialization is done, this hold the basic block
/// that resulted from the splitting.
MachineBasicBlock *DstOrSplit;
/// P is used to update the analysis passes as applicable.
Pass &P;
@ -286,9 +300,11 @@ class RegBankSelect : public MachineFunctionPass {
public:
EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
: InsertPoint(), Src(Src), DstOrSplit(&Dst), P(P) {}
bool isSplit() const override {
return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
}
uint64_t frequency(const Pass &P) const override;
bool canMaterialize() const override;
};
@ -311,9 +327,9 @@ class RegBankSelect : public MachineFunctionPass {
/// \name Convenient types for a list of insertion points.
/// @{
typedef SmallVector<std::unique_ptr<InsertPoint>, 2> InsertionPoints;
typedef InsertionPoints::iterator insertpt_iterator;
typedef InsertionPoints::const_iterator const_insertpt_iterator;
using InsertionPoints = SmallVector<std::unique_ptr<InsertPoint>, 2>;
using insertpt_iterator = InsertionPoints::iterator;
using const_insertpt_iterator = InsertionPoints::const_iterator;
/// @}
private:
@ -324,7 +340,7 @@ class RegBankSelect : public MachineFunctionPass {
/// Are all the insert points materializeable?
bool CanMaterialize;
/// Is there any of the insert points needing splitting?
bool HasSplit;
bool HasSplit = false;
/// Insertion point for the repair code.
/// The repairing code needs to happen just before these points.
InsertionPoints InsertPoints;
@ -407,10 +423,10 @@ class RegBankSelect : public MachineFunctionPass {
private:
/// Cost of the local instructions.
/// This cost is free of basic block frequency.
uint64_t LocalCost;
uint64_t LocalCost = 0;
/// Cost of the non-local instructions.
/// This cost should include the frequency of the related blocks.
uint64_t NonLocalCost;
uint64_t NonLocalCost = 0;
/// Frequency of the block where the local instructions live.
uint64_t LocalFreq;
@ -468,22 +484,22 @@ class RegBankSelect : public MachineFunctionPass {
/// Interface to the target lowering info related
/// to register banks.
const RegisterBankInfo *RBI;
const RegisterBankInfo *RBI = nullptr;
/// MRI contains all the register class/bank information that this
/// pass uses and updates.
MachineRegisterInfo *MRI;
MachineRegisterInfo *MRI = nullptr;
/// Information on the register classes for the current function.
const TargetRegisterInfo *TRI;
const TargetRegisterInfo *TRI = nullptr;
/// Get the frequency of blocks.
/// This is required for non-fast mode.
MachineBlockFrequencyInfo *MBFI;
MachineBlockFrequencyInfo *MBFI = nullptr;
/// Get the frequency of the edges.
/// This is required for non-fast mode.
MachineBranchProbabilityInfo *MBPI;
MachineBranchProbabilityInfo *MBPI = nullptr;
/// Current optimization remark emitter. Used to report failures.
std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
@ -644,6 +660,6 @@ class RegBankSelect : public MachineFunctionPass {
bool runOnMachineFunction(MachineFunction &MF) override;
};
} // End namespace llvm.
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H

View File

@ -1,4 +1,4 @@
//==-- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ----------------*- C++ -*-==//
//===- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -12,26 +12,27 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
#define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
#ifndef LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H
#define LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/MachineValueType.h" // For SimpleValueType.
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <memory> // For unique_ptr.
#include <initializer_list>
#include <memory>
namespace llvm {
class MachineInstr;
class MachineRegisterInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
class raw_ostream;
class RegisterBank;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
/// Holds all the information related to register banks.
class RegisterBankInfo {
@ -48,10 +49,12 @@ class RegisterBankInfo {
/// original value. The bits are counted from less significant
/// bits to most significant bits.
unsigned StartIdx;
/// Length of this mapping in bits. This is how many bits this
/// partial mapping covers in the original value:
/// from StartIdx to StartIdx + Length -1.
unsigned Length;
/// Register bank where the partial value lives.
const RegisterBank *RegBank;
@ -180,13 +183,16 @@ class RegisterBankInfo {
/// Identifier of the mapping.
/// This is used to communicate between the target and the optimizers
/// which mapping should be realized.
unsigned ID;
unsigned ID = InvalidMappingID;
/// Cost of this mapping.
unsigned Cost;
unsigned Cost = 0;
/// Mapping of all the operands.
const ValueMapping *OperandsMapping;
/// Number of operands.
unsigned NumOperands;
unsigned NumOperands = 0;
const ValueMapping &getOperandMapping(unsigned i) {
assert(i < getNumOperands() && "Out of bound operand");
@ -213,7 +219,7 @@ class RegisterBankInfo {
/// Default constructor.
/// Use this constructor to express that the mapping is invalid.
InstructionMapping() : ID(InvalidMappingID), Cost(0), NumOperands(0) {}
InstructionMapping() = default;
/// Get the cost.
unsigned getCost() const { return Cost; }
@ -264,7 +270,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<const InstructionMapping *, 4> InstructionMappings;
using InstructionMappings = SmallVector<const InstructionMapping *, 4>;
/// Helper class used to get/create the virtual registers that will be used
/// to replace the MachineOperand when applying a mapping.
@ -273,12 +279,16 @@ class RegisterBankInfo {
/// OpIdx-th operand starts. -1 means we do not have such mapping yet.
/// Note: We use a SmallVector to avoid heap allocation for most cases.
SmallVector<int, 8> OpToNewVRegIdx;
/// Hold the registers that will be used to map MI with InstrMapping.
SmallVector<unsigned, 8> NewVRegs;
/// Current MachineRegisterInfo, used to create new virtual registers.
MachineRegisterInfo &MRI;
/// Instruction being remapped.
MachineInstr &MI;
/// New mapping of the instruction.
const InstructionMapping &InstrMapping;
@ -373,6 +383,7 @@ class RegisterBankInfo {
protected:
/// Hold the set of supported register banks.
RegisterBank **RegBanks;
/// Total number of register banks.
unsigned NumRegBanks;
@ -729,6 +740,7 @@ operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) {
/// Hashing function for PartialMapping.
/// It is required for the hashing of ValueMapping.
hash_code hash_value(const RegisterBankInfo::PartialMapping &PartMapping);
} // End namespace llvm.
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_REGISTERBANKINFO_H

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===//
//===- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -16,17 +16,19 @@
#define LLVM_CODEGEN_GLOBALISEL_TYPES_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Value.h"
namespace llvm {
class Value;
/// Map a value to a virtual register.
/// For now, we chose to map aggregate types to on single virtual
/// register. This might be revisited if it turns out to be inefficient.
/// PR26161 tracks that.
/// Note: We need to expose this type to the target hooks for thing like
/// ABI lowering that would be used during IRTranslation.
typedef DenseMap<const Value *, unsigned> ValueToVReg;
using ValueToVReg = DenseMap<const Value *, unsigned>;
} // End namespace llvm.
#endif
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_TYPES_H

View File

@ -134,7 +134,7 @@ using MNV = DiagnosticInfoMIROptimization::MachineArgument;
///
/// It allows reporting when optimizations are performed and when they are not
/// along with the reasons for it. Hotness information of the corresponding
/// code region can be included in the remark if DiagnosticHotnessRequested is
/// code region can be included in the remark if DiagnosticsHotnessRequested is
/// enabled in the LLVM context.
class MachineOptimizationRemarkEmitter {
public:

View File

@ -1,4 +1,4 @@
//===-- llvm/CodeGen/MachinePassRegistry.h ----------------------*- C++ -*-===//
//===- llvm/CodeGen/MachinePassRegistry.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -18,13 +18,13 @@
#ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H
#define LLVM_CODEGEN_MACHINEPASSREGISTRY_H
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CommandLine.h"
namespace llvm {
typedef void *(*MachinePassCtor)();
using MachinePassCtor = void *(*)();
//===----------------------------------------------------------------------===//
///
@ -34,36 +34,30 @@ typedef void *(*MachinePassCtor)();
//===----------------------------------------------------------------------===//
class MachinePassRegistryListener {
virtual void anchor();
public:
MachinePassRegistryListener() {}
virtual ~MachinePassRegistryListener() {}
MachinePassRegistryListener() = default;
virtual ~MachinePassRegistryListener() = default;
virtual void NotifyAdd(StringRef N, MachinePassCtor C, StringRef D) = 0;
virtual void NotifyRemove(StringRef N) = 0;
};
//===----------------------------------------------------------------------===//
///
/// MachinePassRegistryNode - Machine pass node stored in registration list.
///
//===----------------------------------------------------------------------===//
class MachinePassRegistryNode {
private:
MachinePassRegistryNode *Next; // Next function pass in list.
MachinePassRegistryNode *Next = nullptr; // Next function pass in list.
StringRef Name; // Name of function pass.
StringRef Description; // Description string.
MachinePassCtor Ctor; // Function pass creator.
public:
MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C)
: Next(nullptr)
, Name(N)
, Description(D)
, Ctor(C)
{}
: Name(N), Description(D), Ctor(C) {}
// Accessors
MachinePassRegistryNode *getNext() const { return Next; }
@ -72,25 +66,20 @@ class MachinePassRegistryNode {
StringRef getDescription() const { return Description; }
MachinePassCtor getCtor() const { return Ctor; }
void setNext(MachinePassRegistryNode *N) { Next = N; }
};
//===----------------------------------------------------------------------===//
///
/// MachinePassRegistry - Track the registration of machine passes.
///
//===----------------------------------------------------------------------===//
class MachinePassRegistry {
private:
MachinePassRegistryNode *List; // List of registry nodes.
MachinePassCtor Default; // Default function pass creator.
MachinePassRegistryListener* Listener;// Listener for list adds are removes.
MachinePassRegistryListener *Listener; // Listener for list adds are removes.
public:
// NO CONSTRUCTOR - we don't want static constructor ordering to mess
// with the registry.
@ -109,10 +98,8 @@ class MachinePassRegistry {
/// Remove - Removes a function pass from the registration list.
///
void Remove(MachinePassRegistryNode *Node);
};
//===----------------------------------------------------------------------===//
///
/// RegisterPassParser class - Handle the addition of new machine passes.
@ -142,7 +129,6 @@ class RegisterPassParser : public MachinePassRegistryListener,
}
// Implement the MachinePassRegistryListener callbacks.
//
void NotifyAdd(StringRef N, MachinePassCtor C, StringRef D) override {
this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D);
}
@ -151,7 +137,6 @@ class RegisterPassParser : public MachinePassRegistryListener,
}
};
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEPASSREGISTRY_H

View File

@ -32,7 +32,7 @@
//
// ScheduleDAGInstrs *<Target>PassConfig::
// createMachineScheduler(MachineSchedContext *C) {
// return new ScheduleDAGMI(C, CustomStrategy(C));
// return new ScheduleDAGMILive(C, CustomStrategy(C));
// }
//
// The DAG builder can also be customized in a sense by adding DAG mutations

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
namespace llvm {
@ -232,8 +233,7 @@ namespace llvm {
Any = 255
};
SimpleValueType SimpleTy;
SimpleValueType SimpleTy = INVALID_SIMPLE_VALUE_TYPE;
// A class to represent the number of elements in a vector
//
@ -270,7 +270,7 @@ namespace llvm {
}
};
constexpr MVT() : SimpleTy(INVALID_SIMPLE_VALUE_TYPE) {}
constexpr MVT() = default;
constexpr MVT(SimpleValueType SVT) : SimpleTy(SVT) {}
bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; }
@ -780,7 +780,6 @@ namespace llvm {
return getSizeInBits() <= VT.getSizeInBits();
}
static MVT getFloatingPointVT(unsigned BitWidth) {
switch (BitWidth) {
default:
@ -982,9 +981,12 @@ namespace llvm {
/// A simple iterator over the MVT::SimpleValueType enum.
struct mvt_iterator {
SimpleValueType VT;
mvt_iterator(SimpleValueType VT) : VT(VT) {}
MVT operator*() const { return VT; }
bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; }
mvt_iterator& operator++() {
VT = (MVT::SimpleValueType)((int)VT + 1);
assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE &&
@ -992,8 +994,9 @@ namespace llvm {
return *this;
}
};
/// A range of the MVT::SimpleValueType enum.
typedef iterator_range<mvt_iterator> mvt_range;
using mvt_range = iterator_range<mvt_iterator>;
public:
/// SimpleValueType Iteration
@ -1001,32 +1004,39 @@ namespace llvm {
static mvt_range all_valuetypes() {
return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE);
}
static mvt_range integer_valuetypes() {
return mvt_range(MVT::FIRST_INTEGER_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1));
}
static mvt_range fp_valuetypes() {
return mvt_range(MVT::FIRST_FP_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1));
}
static mvt_range vector_valuetypes() {
return mvt_range(MVT::FIRST_VECTOR_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1));
}
static mvt_range integer_vector_valuetypes() {
return mvt_range(
MVT::FIRST_INTEGER_VECTOR_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1));
}
static mvt_range fp_vector_valuetypes() {
return mvt_range(
MVT::FIRST_FP_VECTOR_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1));
}
static mvt_range integer_scalable_vector_valuetypes() {
return mvt_range(MVT::FIRST_INTEGER_SCALABLE_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_INTEGER_SCALABLE_VALUETYPE + 1));
}
static mvt_range fp_scalable_vector_valuetypes() {
return mvt_range(MVT::FIRST_FP_SCALABLE_VALUETYPE,
(MVT::SimpleValueType)(MVT::LAST_FP_SCALABLE_VALUETYPE + 1));
@ -1034,6 +1044,6 @@ namespace llvm {
/// @}
};
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_MACHINEVALUETYPE_H

View File

@ -1,4 +1,4 @@
//===- MacroFusion.h - Macro Fusion ------------------------===//
//===- MacroFusion.h - Macro Fusion -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -12,19 +12,26 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_MACROFUSION_H
#define LLVM_CODEGEN_MACROFUSION_H
#include <functional>
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include <memory>
namespace llvm {
class MachineInstr;
class ScheduleDAGMutation;
class TargetInstrInfo;
class TargetSubtargetInfo;
/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused
/// together. Given SecondMI, when FirstMI is unspecified, then check if
/// SecondMI may be part of a fused pair at all.
typedef std::function<bool(const TargetInstrInfo &TII,
const TargetSubtargetInfo &TSI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI)> ShouldSchedulePredTy;
using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII,
const TargetSubtargetInfo &TSI,
const MachineInstr *FirstMI,
const MachineInstr &SecondMI)>;
/// \brief Create a DAG scheduling mutation to pair instructions back to back
/// for instructions that benefit according to the target-specific
@ -39,3 +46,5 @@ std::unique_ptr<ScheduleDAGMutation>
createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
} // end namespace llvm
#endif // LLVM_CODEGEN_MACROFUSION_H

View File

@ -94,7 +94,7 @@ class FixedStackPseudoSourceValue : public PseudoSourceValue {
explicit FixedStackPseudoSourceValue(int FI)
: PseudoSourceValue(FixedStack), FI(FI) {}
static inline bool classof(const PseudoSourceValue *V) {
static bool classof(const PseudoSourceValue *V) {
return V->kind() == FixedStack;
}
@ -126,7 +126,7 @@ class GlobalValuePseudoSourceValue : public CallEntryPseudoSourceValue {
public:
GlobalValuePseudoSourceValue(const GlobalValue *GV);
static inline bool classof(const PseudoSourceValue *V) {
static bool classof(const PseudoSourceValue *V) {
return V->kind() == GlobalValueCallEntry;
}
@ -140,7 +140,7 @@ class ExternalSymbolPseudoSourceValue : public CallEntryPseudoSourceValue {
public:
ExternalSymbolPseudoSourceValue(const char *ES);
static inline bool classof(const PseudoSourceValue *V) {
static bool classof(const PseudoSourceValue *V) {
return V->kind() == ExternalSymbolCallEntry;
}

View File

@ -57,7 +57,7 @@ class BaseIndexOffset {
int64_t &Off);
/// Parses tree in Ptr for base, index, offset addresses.
static BaseIndexOffset match(SDValue Ptr);
static BaseIndexOffset match(SDValue Ptr, const SelectionDAG &DAG);
};
} // namespace llvm

View File

@ -1743,7 +1743,7 @@ class BuildVectorSDNode : public SDNode {
bool isConstant() const;
static inline bool classof(const SDNode *N) {
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::BUILD_VECTOR;
}
};

View File

@ -1,4 +1,4 @@
//===-- TargetPassConfig.h - Code Generation pass options -------*- C++ -*-===//
//===- TargetPassConfig.h - Code Generation pass options --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -16,19 +16,23 @@
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include <cassert>
#include <string>
namespace llvm {
class PassConfigImpl;
class ScheduleDAGInstrs;
class LLVMTargetMachine;
struct MachineSchedContext;
class PassConfigImpl;
class ScheduleDAGInstrs;
// The old pass manager infrastructure is hidden in a legacy namespace now.
namespace legacy {
class PassManagerBase;
}
} // end namespace legacy
using legacy::PassManagerBase;
/// Discriminated union of Pass ID types.
@ -50,10 +54,11 @@ class IdentifyingPassPtr {
AnalysisID ID;
Pass *P;
};
bool IsInstance;
bool IsInstance = false;
public:
IdentifyingPassPtr() : P(nullptr), IsInstance(false) {}
IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {}
IdentifyingPassPtr() : P(nullptr) {}
IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr) {}
IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {}
bool isValid() const { return P; }
@ -63,6 +68,7 @@ class IdentifyingPassPtr {
assert(!IsInstance && "Not a Pass ID");
return ID;
}
Pass *getInstance() const {
assert(IsInstance && "Not a Pass Instance");
return P;
@ -93,31 +99,30 @@ class TargetPassConfig : public ImmutablePass {
static char PostRAMachineLICMID;
private:
PassManagerBase *PM;
PassManagerBase *PM = nullptr;
AnalysisID StartBefore = nullptr;
AnalysisID StartAfter = nullptr;
AnalysisID StopBefore = nullptr;
AnalysisID StopAfter = nullptr;
bool Started;
bool Stopped;
bool AddingMachinePasses;
bool Started = true;
bool Stopped = false;
bool AddingMachinePasses = false;
protected:
LLVMTargetMachine *TM;
PassConfigImpl *Impl; // Internal data structures
bool Initialized; // Flagged after all passes are configured.
PassConfigImpl *Impl = nullptr; // Internal data structures
bool Initialized = false; // Flagged after all passes are configured.
// Target Pass Options
// Targets provide a default setting, user flags override.
//
bool DisableVerify;
bool DisableVerify = false;
/// Default setting for -enable-tail-merge on this target.
bool EnableTailMerge;
bool EnableTailMerge = true;
/// Require processing of functions such that callees are generated before
/// callers.
bool RequireCodeGenSCCOrder;
bool RequireCodeGenSCCOrder = false;
/// Add the actual instruction selection passes. This does not include
/// preparation passes on IR.
@ -296,7 +301,6 @@ class TargetPassConfig : public ImmutablePass {
/// printAndVerify - Add a pass to dump then verify the machine function, if
/// those steps are enabled.
///
void printAndVerify(const std::string &Banner);
/// Add a pass to print the machine function if printing is enabled.
@ -430,4 +434,4 @@ class TargetPassConfig : public ImmutablePass {
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_TARGETPASSCONFIG_H

View File

@ -17,7 +17,10 @@
#define LLVM_CODEGEN_VALUETYPES_H
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
#include <string>
namespace llvm {
@ -30,13 +33,13 @@ namespace llvm {
/// can represent.
struct EVT {
private:
MVT V;
Type *LLVMTy;
MVT V = MVT::INVALID_SIMPLE_VALUE_TYPE;
Type *LLVMTy = nullptr;
public:
constexpr EVT() : V(MVT::INVALID_SIMPLE_VALUE_TYPE), LLVMTy(nullptr) {}
constexpr EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) {}
constexpr EVT(MVT S) : V(S), LLVMTy(nullptr) {}
constexpr EVT() = default;
constexpr EVT(MVT::SimpleValueType SVT) : V(SVT) {}
constexpr EVT(MVT S) : V(S) {}
bool operator==(EVT VT) const {
return !(*this != VT);
@ -246,7 +249,6 @@ namespace llvm {
return getSizeInBits() <= VT.getSizeInBits();
}
/// Return the SimpleValueType held in the specified simple EVT.
MVT getSimpleVT() const {
assert(isSimple() && "Expected a SimpleValueType!");
@ -430,6 +432,6 @@ namespace llvm {
unsigned getExtendedSizeInBits() const LLVM_READONLY;
};
} // End llvm namespace
} // end namespace llvm
#endif
#endif // LLVM_CODEGEN_VALUETYPES_H

View File

@ -25,7 +25,9 @@ class CVSymbolVisitor {
CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks);
Error visitSymbolRecord(CVSymbol &Record);
Error visitSymbolRecord(CVSymbol &Record, uint32_t Offset);
Error visitSymbolStream(const CVSymbolArray &Symbols);
Error visitSymbolStream(const CVSymbolArray &Symbols, uint32_t InitialOffset);
private:
SymbolVisitorCallbacks &Callbacks;

View File

@ -12,13 +12,19 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
class DebugStringTableSubsection;
@ -28,24 +34,22 @@ struct FileChecksumEntry {
FileChecksumKind Kind; // The type of checksum.
ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
};
}
}
namespace llvm {
} // end namespace codeview
template <> struct VarStreamArrayExtractor<codeview::FileChecksumEntry> {
public:
typedef void ContextType;
using ContextType = void;
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::FileChecksumEntry &Item);
};
}
namespace llvm {
namespace codeview {
class DebugChecksumsSubsectionRef final : public DebugSubsectionRef {
typedef VarStreamArray<codeview::FileChecksumEntry> FileChecksumArray;
typedef FileChecksumArray::Iterator Iterator;
using FileChecksumArray = VarStreamArray<codeview::FileChecksumEntry>;
using Iterator = FileChecksumArray::Iterator;
public:
DebugChecksumsSubsectionRef()
@ -89,10 +93,12 @@ class DebugChecksumsSubsection final : public DebugSubsection {
DenseMap<uint32_t, uint32_t> OffsetMap;
uint32_t SerializedSize = 0;
llvm::BumpPtrAllocator Storage;
BumpPtrAllocator Storage;
std::vector<FileChecksumEntry> Checksums;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H

View File

@ -10,18 +10,21 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <map>
namespace llvm {
namespace codeview {
class DebugCrossModuleExportsSubsectionRef final : public DebugSubsectionRef {
typedef FixedStreamArray<CrossModuleExport> ReferenceArray;
typedef ReferenceArray::Iterator Iterator;
using ReferenceArray = FixedStreamArray<CrossModuleExport>;
using Iterator = ReferenceArray::Iterator;
public:
DebugCrossModuleExportsSubsectionRef()
@ -58,7 +61,8 @@ class DebugCrossModuleExportsSubsection final : public DebugSubsection {
private:
std::map<uint32_t, uint32_t> Mappings;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSEXSUBSECTION_H

View File

@ -11,38 +11,43 @@
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
struct CrossModuleImportItem {
const CrossModuleImport *Header = nullptr;
llvm::FixedStreamArray<support::ulittle32_t> Imports;
FixedStreamArray<support::ulittle32_t> Imports;
};
}
}
namespace llvm {
} // end namespace codeview
template <> struct VarStreamArrayExtractor<codeview::CrossModuleImportItem> {
public:
typedef void ContextType;
using ContextType = void;
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::CrossModuleImportItem &Item);
};
}
namespace llvm {
namespace codeview {
class DebugStringTableSubsection;
class DebugCrossModuleImportsSubsectionRef final : public DebugSubsectionRef {
typedef VarStreamArray<CrossModuleImportItem> ReferenceArray;
typedef ReferenceArray::Iterator Iterator;
using ReferenceArray = VarStreamArray<CrossModuleImportItem>;
using Iterator = ReferenceArray::Iterator;
public:
DebugCrossModuleImportsSubsectionRef()
@ -82,7 +87,9 @@ class DebugCrossModuleImportsSubsection final : public DebugSubsection {
DebugStringTableSubsection &Strings;
StringMap<std::vector<support::ulittle32_t>> Mappings;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGCROSSIMPSUBSECTION_H

View File

@ -7,19 +7,26 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_BUGINLINEELINESSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_BUGINLINEELINESSUBSECTION_H
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
class DebugInlineeLinesSubsectionRef;
class DebugChecksumsSubsection;
enum class InlineeLinesSignature : uint32_t {
@ -40,18 +47,21 @@ struct InlineeSourceLine {
const InlineeSourceLineHeader *Header;
FixedStreamArray<support::ulittle32_t> ExtraFiles;
};
}
} // end namespace codeview
template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> {
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::InlineeSourceLine &Item);
bool HasExtraFiles = false;
};
namespace codeview {
class DebugInlineeLinesSubsectionRef final : public DebugSubsectionRef {
typedef VarStreamArray<InlineeSourceLine> LinesArray;
typedef LinesArray::Iterator Iterator;
using LinesArray = VarStreamArray<InlineeSourceLine>;
using Iterator = LinesArray::Iterator;
public:
DebugInlineeLinesSubsectionRef();
@ -99,13 +109,13 @@ class DebugInlineeLinesSubsection final : public DebugSubsection {
private:
DebugChecksumsSubsection &Checksums;
bool HasExtraFiles = false;
uint32_t ExtraFileCount = 0;
std::vector<Entry> Entries;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGINLINEELINESSUBSECTION_H

View File

@ -1,4 +1,4 @@
//===- DebugLinesSubsection.h --------------------------------*- C++ -*-===//
//===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -7,14 +7,20 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
@ -72,8 +78,9 @@ class LineColumnExtractor {
class DebugLinesSubsectionRef final : public DebugSubsectionRef {
friend class LineColumnExtractor;
typedef VarStreamArray<LineColumnEntry, LineColumnExtractor> LineInfoArray;
typedef LineInfoArray::Iterator Iterator;
using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>;
using Iterator = LineInfoArray::Iterator;
public:
DebugLinesSubsectionRef();
@ -130,14 +137,14 @@ class DebugLinesSubsection final : public DebugSubsection {
private:
DebugChecksumsSubsection &Checksums;
uint32_t RelocOffset = 0;
uint16_t RelocSegment = 0;
uint32_t CodeSize = 0;
LineFlags Flags = LF_None;
std::vector<Block> Blocks;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H

View File

@ -12,17 +12,15 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <stdint.h>
#include <cstdint>
namespace llvm {
class BinaryStreamReader;
class BinaryStreamRef;
class BinaryStreamWriter;
namespace codeview {
@ -83,7 +81,9 @@ class DebugStringTableSubsection : public DebugSubsection {
StringMap<uint32_t> Strings;
uint32_t StringSize = 1;
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H

View File

@ -1,4 +1,4 @@
//===- DebugSubsection.h ------------------------------------*- C++ -*-===//
//===- DebugSubsectionRecord.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -7,17 +7,22 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include <cstdint>
#include <memory>
namespace llvm {
class BinaryStreamWriter;
namespace codeview {
class DebugSubsection;
@ -42,8 +47,8 @@ class DebugSubsectionRecord {
BinaryStreamRef getRecordData() const;
private:
CodeViewContainer Container;
DebugSubsectionKind Kind;
CodeViewContainer Container = CodeViewContainer::ObjectFile;
DebugSubsectionKind Kind = DebugSubsectionKind::None;
BinaryStreamRef Data;
};
@ -71,7 +76,7 @@ class DebugSubsectionRecordBuilder {
CodeViewContainer Container;
};
} // namespace codeview
} // end namespace codeview
template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> {
Error operator()(BinaryStreamRef Stream, uint32_t &Length,
@ -88,8 +93,11 @@ template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> {
};
namespace codeview {
typedef VarStreamArray<DebugSubsectionRecord> DebugSubsectionArray;
}
} // namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H
using DebugSubsectionArray = VarStreamArray<DebugSubsectionRecord>;
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSUBSECTIONRECORD_H

View File

@ -10,17 +10,23 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
class BinaryStreamReader;
namespace codeview {
class DebugSymbolRVASubsectionRef final : public DebugSubsectionRef {
public:
typedef FixedStreamArray<support::ulittle32_t> ArrayType;
using ArrayType = FixedStreamArray<support::ulittle32_t>;
DebugSymbolRVASubsectionRef();
@ -53,7 +59,9 @@ class DebugSymbolRVASubsection final : public DebugSubsection {
private:
std::vector<support::ulittle32_t> RVAs;
};
} // namespace codeview
} // namespace llvm
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLRVASUBSECTION_H

View File

@ -1,4 +1,4 @@
//===- EnumTables.h Enum to string conversion tables ------------*- C++ -*-===//
//===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -14,11 +14,11 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/Support/ScopedPrinter.h"
#include <stdint.h>
#include <cstdint>
namespace llvm {
namespace codeview {
ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames();
ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames();
ArrayRef<EnumEntry<uint16_t>> getRegisterNames();
@ -38,7 +38,8 @@ ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames();
ArrayRef<EnumEntry<uint16_t>> getTrampolineNames();
ArrayRef<EnumEntry<COFF::SectionCharacteristics>>
getImageSectionCharacteristicNames();
} // namespace codeview
} // namespace llvm
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_ENUMTABLES_H

View File

@ -14,21 +14,27 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
namespace llvm {
namespace codeview {
namespace detail {
class GuidAdapter final : public llvm::FormatAdapter<ArrayRef<uint8_t>> {
class GuidAdapter final : public FormatAdapter<ArrayRef<uint8_t>> {
ArrayRef<uint8_t> Guid;
public:
explicit GuidAdapter(ArrayRef<uint8_t> Guid);
explicit GuidAdapter(StringRef Guid);
void format(llvm::raw_ostream &Stream, StringRef Style);
void format(raw_ostream &Stream, StringRef Style) override ;
};
}
} // end namespace detail
inline detail::GuidAdapter fmt_guid(StringRef Item) {
return detail::GuidAdapter(Item);
@ -37,11 +43,12 @@ inline detail::GuidAdapter fmt_guid(StringRef Item) {
inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) {
return detail::GuidAdapter(Item);
}
}
} // end namespace codeview
template <> struct format_provider<codeview::TypeIndex> {
public:
static void format(const codeview::TypeIndex &V, llvm::raw_ostream &Stream,
static void format(const codeview::TypeIndex &V, raw_ostream &Stream,
StringRef Style) {
if (V.isNoneType())
Stream << "<no type>";
@ -52,6 +59,7 @@ template <> struct format_provider<codeview::TypeIndex> {
}
}
};
}
#endif
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H

View File

@ -1,4 +1,4 @@
//===- LazyRandomTypeCollection.h ---------------------------- *- C++ --*-===//
//===- LazyRandomTypeCollection.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -10,12 +10,18 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/StringSaver.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
@ -43,7 +49,8 @@ namespace codeview {
/// into M chunks of roughly equal size, this yields a worst case lookup time
/// of O(N/M) and an amortized time of O(1).
class LazyRandomTypeCollection : public TypeCollection {
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
using PartialOffsetArray = FixedStreamArray<TypeIndexOffset>;
struct CacheEntry {
CVType Type;
uint32_t Offset;

View File

@ -7,23 +7,18 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H
#define LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H
#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H
#define LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include <memory>
namespace llvm {
namespace codeview {
class DebugSubsectionRecord;
class DebugChecksumsSubsectionRef;
class DebugStringTableSubsectionRef;
class DebugChecksumsSubsection;
class DebugStringTableSubsection;
class StringsAndChecksumsRef {
public:
// If no subsections are known about initially, we find as much as we can.
@ -83,8 +78,9 @@ class StringsAndChecksums {
public:
using StringsPtr = std::shared_ptr<DebugStringTableSubsection>;
using ChecksumsPtr = std::shared_ptr<DebugChecksumsSubsection>;
// If no subsections are known about initially, we find as much as we can.
StringsAndChecksums() {}
StringsAndChecksums() = default;
void setStrings(const StringsPtr &SP) { Strings = SP; }
void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; }
@ -100,7 +96,7 @@ class StringsAndChecksums {
ChecksumsPtr Checksums;
};
} // namespace codeview
} // namespace llvm
} // end namespace codeview
} // end namespace llvm
#endif
#endif // LLVM_DEBUGINFO_CODEVIEW_STRINGSANDCHECKSUMS_H

View File

@ -51,6 +51,10 @@ class SymbolDeserializer : public SymbolVisitorCallbacks {
CodeViewContainer Container)
: Delegate(Delegate), Container(Container) {}
Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override {
return visitSymbolBegin(Record);
}
Error visitSymbolBegin(CVSymbol &Record) override {
assert(!Mapping && "Already in a symbol mapping!");
Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container);

View File

@ -21,8 +21,6 @@
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstddef>
#include <cstdint>
#include <vector>
@ -35,6 +33,7 @@ class SymbolRecord {
public:
SymbolRecordKind getKind() const { return Kind; }
SymbolRecordKind Kind;
};
@ -153,6 +152,7 @@ class CallerSym : public SymbolRecord {
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
std::vector<TypeIndex> Indices;
uint32_t RecordOffset;
};
@ -165,8 +165,8 @@ struct BinaryAnnotationIterator {
int32_t S1;
};
BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
BinaryAnnotationIterator() = default;
BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
: Data(Other.Data) {}
@ -342,9 +342,9 @@ class InlineSiteSym : public SymbolRecord {
: SymbolRecord(SymbolRecordKind::InlineSiteSym),
RecordOffset(RecordOffset) {}
llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
return llvm::make_range(BinaryAnnotationIterator(AnnotationData),
BinaryAnnotationIterator());
iterator_range<BinaryAnnotationIterator> annotations() const {
return make_range(BinaryAnnotationIterator(AnnotationData),
BinaryAnnotationIterator());
}
uint32_t Parent;
@ -479,6 +479,7 @@ class DefRangeRegisterSym : public SymbolRecord {
ulittle16_t Register;
ulittle16_t MayHaveNoName;
};
explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
DefRangeRegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
@ -501,6 +502,7 @@ class DefRangeSubfieldRegisterSym : public SymbolRecord {
ulittle16_t MayHaveNoName;
ulittle32_t OffsetInParent;
};
explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
@ -546,6 +548,7 @@ class DefRangeRegisterRelSym : public SymbolRecord {
ulittle16_t Flags;
little32_t BasePointerOffset;
};
explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@ -935,8 +938,8 @@ class ThreadLocalDataSym : public SymbolRecord {
uint32_t RecordOffset;
};
typedef CVRecord<SymbolKind> CVSymbol;
typedef VarStreamArray<CVSymbol> CVSymbolArray;
using CVSymbol = CVRecord<SymbolKind>;
using CVSymbolArray = VarStreamArray<CVSymbol>;
} // end namespace codeview
} // end namespace llvm

View File

@ -1,4 +1,4 @@
//===- symbolSerializer.h ---------------------------------------*- C++ -*-===//
//===- SymbolSerializer.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -10,21 +10,20 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
class BinaryStreamWriter;
namespace codeview {
class SymbolSerializer : public SymbolVisitorCallbacks {
@ -45,6 +44,8 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
}
public:
SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container);
template <typename SymType>
static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage,
CodeViewContainer Container) {
@ -57,13 +58,11 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
return Result;
}
SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container);
virtual Error visitSymbolBegin(CVSymbol &Record) override;
virtual Error visitSymbolEnd(CVSymbol &Record) override;
Error visitSymbolBegin(CVSymbol &Record) override;
Error visitSymbolEnd(CVSymbol &Record) override;
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \
Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \
return visitKnownRecordImpl(CVR, Record); \
}
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
@ -75,7 +74,8 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
return Mapping.visitKnownRecord(CVR, Record);
}
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H

View File

@ -30,6 +30,14 @@ class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks {
return Error::success();
}
Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitSymbolBegin(Record, Offset))
return EC;
}
return Error::success();
}
Error visitSymbolBegin(CVSymbol &Record) override {
for (auto Visitor : Pipeline) {
if (auto EC = Visitor->visitSymbolBegin(Record))

View File

@ -29,8 +29,10 @@ class SymbolVisitorCallbacks {
/// Paired begin/end actions for all symbols. Receives all record data,
/// including the fixed-length record prefix. visitSymbolBegin() should
/// return
/// the type of the Symbol, or an error if it cannot be determined.
/// return the type of the Symbol, or an error if it cannot be determined.
virtual Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) {
return Error::success();
}
virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); }
virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); }

View File

@ -28,6 +28,8 @@ void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
SmallVectorImpl<TiReference> &Refs);
void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TiReference> &Refs);
void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TypeIndex> &Indices);
/// Discover type indices in symbol records. Returns false if this is an unknown
/// record.

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
@ -25,31 +26,30 @@
#include <vector>
namespace llvm {
class BinaryStreamReader;
namespace codeview {
using support::little32_t;
using support::ulittle16_t;
using support::ulittle32_t;
typedef CVRecord<TypeLeafKind> CVType;
typedef RemappedRecord<TypeLeafKind> RemappedType;
using CVType = CVRecord<TypeLeafKind>;
using RemappedType = RemappedRecord<TypeLeafKind>;
struct CVMemberRecord {
TypeLeafKind Kind;
ArrayRef<uint8_t> Data;
};
typedef VarStreamArray<CVType> CVTypeArray;
typedef iterator_range<CVTypeArray::Iterator> CVTypeRange;
using CVTypeArray = VarStreamArray<CVType>;
using CVTypeRange = iterator_range<CVTypeArray::Iterator>;
/// Equvalent to CV_fldattr_t in cvinfo.h.
struct MemberAttributes {
uint16_t Attrs = 0;
enum {
MethodKindShift = 2,
};
MemberAttributes() = default;
explicit MemberAttributes(MemberAccess Access)
@ -226,6 +226,7 @@ class MemberFuncIdRecord : public TypeRecord {
TypeIndex getClassType() const { return ClassType; }
TypeIndex getFunctionType() const { return FunctionType; }
StringRef getName() const { return Name; }
TypeIndex ClassType;
TypeIndex FunctionType;
StringRef Name;
@ -330,7 +331,6 @@ class PointerRecord : public TypeRecord {
TypeIndex ReferentType;
uint32_t Attrs;
Optional<MemberPointerInfo> MemberInfo;
private:
@ -490,6 +490,7 @@ class EnumRecord : public TagRecord {
UnderlyingType(UnderlyingType) {}
TypeIndex getUnderlyingType() const { return UnderlyingType; }
TypeIndex UnderlyingType;
};
@ -505,6 +506,7 @@ class BitFieldRecord : public TypeRecord {
TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; }
uint8_t getBitSize() const { return BitSize; }
TypeIndex Type;
uint8_t BitSize;
uint8_t BitOffset;
@ -527,6 +529,7 @@ class VFTableShapeRecord : public TypeRecord {
}
uint32_t getEntryCount() const { return getSlots().size(); }
ArrayRef<VFTableSlotKind> SlotsRef;
std::vector<VFTableSlotKind> Slots;
};
@ -541,9 +544,7 @@ class TypeServer2Record : public TypeRecord {
Name(Name) {}
StringRef getGuid() const { return Guid; }
uint32_t getAge() const { return Age; }
StringRef getName() const { return Name; }
StringRef Guid;
@ -560,8 +561,8 @@ class StringIdRecord : public TypeRecord {
: TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
TypeIndex getId() const { return Id; }
StringRef getString() const { return String; }
TypeIndex Id;
StringRef String;
};
@ -576,9 +577,7 @@ class FuncIdRecord : public TypeRecord {
FunctionType(FunctionType), Name(Name) {}
TypeIndex getParentScope() const { return ParentScope; }
TypeIndex getFunctionType() const { return FunctionType; }
StringRef getName() const { return Name; }
TypeIndex ParentScope;
@ -635,6 +634,7 @@ class BuildInfoRecord : public TypeRecord {
ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
SmallVector<TypeIndex, 4> ArgIndices;
};
@ -656,6 +656,7 @@ class VFTableRecord : public TypeRecord {
TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
uint32_t getVFPtrOffset() const { return VFPtrOffset; }
StringRef getName() const { return makeArrayRef(MethodNames).front(); }
ArrayRef<StringRef> getMethodNames() const {
return makeArrayRef(MethodNames).drop_front();
}
@ -707,6 +708,7 @@ class MethodOverloadListRecord : public TypeRecord {
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
std::vector<OneMethodRecord> Methods;
};
@ -723,6 +725,7 @@ class OverloadedMethodRecord : public TypeRecord {
uint16_t getNumOverloads() const { return NumOverloads; }
TypeIndex getMethodList() const { return MethodList; }
StringRef getName() const { return Name; }
uint16_t NumOverloads;
TypeIndex MethodList;
StringRef Name;
@ -874,7 +877,6 @@ class ListContinuationRecord : public TypeRecord {
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H

View File

@ -10,19 +10,25 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <vector>
namespace llvm {
namespace codeview {
class TypeHasher;
@ -46,7 +52,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
}
};
typedef SmallVector<MutableArrayRef<uint8_t>, 2> MutableRecordList;
using MutableRecordList = SmallVector<MutableArrayRef<uint8_t>, 2>;
static constexpr uint8_t ContinuationLength = 8;
BumpPtrAllocator &RecordStorage;
@ -82,7 +88,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
public:
explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
~TypeSerializer();
~TypeSerializer() override;
void reset();
@ -146,7 +152,8 @@ class TypeSerializer : public TypeVisitorCallbacks {
return Error::success();
}
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H

View File

@ -10,16 +10,17 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
class TypeServer2Record;
class TypeVisitorCallbacks;
class TypeServerHandler {
public:
virtual ~TypeServerHandler() {}
virtual ~TypeServerHandler() = default;
/// Handle a TypeServer record. If the implementation returns true
/// the record will not be processed by the top-level visitor. If
@ -30,7 +31,8 @@ class TypeServerHandler {
return false;
}
};
}
}
#endif
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H

View File

@ -12,8 +12,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
#include <cstdint>
#include <utility>
@ -41,20 +41,31 @@ class DWARFAcceleratorTable {
struct Header Hdr;
struct HeaderData HdrData;
DataExtractor AccelSection;
DWARFDataExtractor AccelSection;
DataExtractor StringSection;
const RelocAddrMap& Relocs;
public:
DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection,
const RelocAddrMap &Relocs)
: AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {}
DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
DataExtractor StringSection)
: AccelSection(AccelSection), StringSection(StringSection) {}
bool extract();
uint32_t getNumBuckets();
uint32_t getNumHashes();
uint32_t getSizeHdr();
uint32_t getHeaderDataLength();
ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
bool validateForms();
/// Return information related to the DWARF DIE we're looking for when
/// performing a lookup by name.
///
/// \param HashDataOffset an offset into the hash data table
/// \returns DIEOffset the offset into the .debug_info section for the DIE
/// related to the input hash data offset. Currently this function returns
/// only the DIEOffset but it can be modified to return more data regarding
/// the DIE
uint32_t readAtoms(uint32_t &HashDataOffset);
void dump(raw_ostream &OS) const;
};

View File

@ -20,8 +20,8 @@ class DWARFCompileUnit : public DWARFUnit {
DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, StringRef LS, bool LE, bool IsDWO,
const DWARFUnitSectionBase &UnitSection,
const DWARFSection *AOS, const DWARFSection &LS, bool LE,
bool IsDWO, const DWARFUnitSectionBase &UnitSection,
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
UnitSection, Entry) {}

Some files were not shown because too many files have changed in this diff Show More