Import magic pass from llvm-apps
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
This commit is contained in:
parent
b5e2faaaaf
commit
3e457fe321
33 changed files with 11046 additions and 227 deletions
148
minix/llvm/include/common/util/stdlib.h
Normal file
148
minix/llvm/include/common/util/stdlib.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
#ifndef _UTIL_STDLIB_H
|
||||
#define _UTIL_STDLIB_H
|
||||
|
||||
#include "util_def.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct util_stdlib_s {
|
||||
int id;
|
||||
char *name;
|
||||
unsigned long flags;
|
||||
} util_stdlib_t;
|
||||
|
||||
typedef enum util_stdlib_id_e {
|
||||
STDLIB_ACCEPT = 0,
|
||||
STDLIB_ACCEPT4,
|
||||
STDLIB_BIND,
|
||||
STDLIB_BRK,
|
||||
STDLIB_CALLOC,
|
||||
STDLIB_EPOLL_CREATE,
|
||||
STDLIB_EPOLL_CREATE1,
|
||||
STDLIB_EPOLL_WAIT,
|
||||
STDLIB_FREE,
|
||||
STDLIB_GETSOCKOPT,
|
||||
STDLIB_KILL,
|
||||
STDLIB_LISTEN,
|
||||
STDLIB_MALLOC,
|
||||
STDLIB_MEMALIGN,
|
||||
STDLIB_MMAP,
|
||||
STDLIB_MMAP64,
|
||||
STDLIB_MUNMAP,
|
||||
STDLIB_POLL,
|
||||
STDLIB_POSIX_MEMALIGN,
|
||||
STDLIB_PPOLL,
|
||||
STDLIB_PTHREAD_COND_WAIT,
|
||||
STDLIB_PTHREAD_COND_TIMEDWAIT,
|
||||
STDLIB_PTHREAD_JOIN,
|
||||
STDLIB_READ,
|
||||
STDLIB_REALLOC,
|
||||
STDLIB_RECV,
|
||||
STDLIB_RECVFROM,
|
||||
STDLIB_RECVMSG,
|
||||
STDLIB_SBRK,
|
||||
STDLIB_SELECT,
|
||||
STDLIB_SEMOP,
|
||||
STDLIB_SEMTIMEDOP,
|
||||
STDLIB_SETSOCKOPT,
|
||||
STDLIB_SHMAT,
|
||||
STDLIB_SHMDT,
|
||||
STDLIB_SIGSUSPEND,
|
||||
STDLIB_SIGTIMEDWAIT,
|
||||
STDLIB_SIGWAITINFO,
|
||||
STDLIB_SLEEP,
|
||||
STDLIB_SOCKET,
|
||||
STDLIB_USLEEP,
|
||||
STDLIB_VALLOC,
|
||||
STDLIB_WAITPID,
|
||||
__NUM_STDLIBS_IDS
|
||||
} util_stdlib_id_t;
|
||||
|
||||
typedef enum util_stdlib_flag_e {
|
||||
STLIB_BLOCK_EXT = 0,
|
||||
STLIB_BLOCK_INT,
|
||||
__NUM_STDLIBS_FLAGS
|
||||
} util_stdlib_flag_t;
|
||||
#define _UTIL_STLIB_FLAGS_STR "ei"
|
||||
|
||||
#define _UTIL_STLIB_FLAG(F) (1 << (F))
|
||||
#define _UTIL_STLIB_BLOCK_MASK \
|
||||
(_UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)|_UTIL_STLIB_FLAG(STLIB_BLOCK_INT))
|
||||
|
||||
#define _UTIL_STLIB_FLAGS_STR_BUFF_SIZE (__NUM_STDLIBS_FLAGS+1)
|
||||
#define _UTIL_STLIB_FLAG_C(F, E) \
|
||||
(((F) & _UTIL_STLIB_FLAG(E)) ? _UTIL_STLIB_FLAGS_STR[E] : '-')
|
||||
|
||||
#define _UTIL_STDLIB_DEF(ID, N, F) { (ID), (N), (F) }
|
||||
#define _UTIL_STDLIBS_INITIALIZER { \
|
||||
_UTIL_STDLIB_DEF(STDLIB_ACCEPT, "accept", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_ACCEPT4, "accept4", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_BIND, "bind", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_BRK, "brk", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_CALLOC, "calloc", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE, "epoll_create", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_EPOLL_CREATE1, "epoll_create1", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_EPOLL_WAIT, "epoll_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_FREE, "free", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_GETSOCKOPT, "getsockopt", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_KILL, "kill", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_LISTEN, "listen", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_MALLOC, "malloc", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_MEMALIGN, "memalign", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_MMAP, "mmap", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_MMAP64, "mmap64", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_MUNMAP, "munmap", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_POLL, "poll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_POSIX_MEMALIGN, "posix_memalign", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_PPOLL, "ppoll", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_WAIT, "pthread_cond_wait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_COND_TIMEDWAIT, "pthread_cond_timedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_PTHREAD_JOIN, "pthread_join", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_READ, "read", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_REALLOC, "realloc", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_RECV, "recv", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_RECVFROM, "recvfrom", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_RECVMSG, "recvsmg", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SBRK, "sbrk", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SELECT, "select", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SEMOP, "semop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SEMTIMEDOP, "semtimedop", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SETSOCKOPT, "setsockopt", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SHMAT, "shmat", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SHMDT, "shmdt", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SIGSUSPEND, "sigsuspend", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SIGTIMEDWAIT, "sigtimedwait", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SIGWAITINFO, "sigwaitinfo", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SLEEP, "sleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_SOCKET, "socket", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_USLEEP, "usleep", _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_VALLOC, "valloc", 0), \
|
||||
_UTIL_STDLIB_DEF(STDLIB_WAITPID, "waitpid", _UTIL_STLIB_FLAG(STLIB_BLOCK_INT)) \
|
||||
}
|
||||
|
||||
static inline util_stdlib_t* util_stdlib_lookup_by_name(const char *name, util_stdlib_t *stlib_arr)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<__NUM_STDLIBS_IDS;i++) {
|
||||
if (!strcmp(name, stlib_arr[i].name)) {
|
||||
return &stlib_arr[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char* util_stdlib_flags_to_str(unsigned long flags,
|
||||
char* buffer)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<__NUM_STDLIBS_FLAGS;i++) {
|
||||
buffer[i] = _UTIL_STLIB_FLAG_C(flags, i);
|
||||
}
|
||||
buffer[i] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif /* _UTIL_STDLIB_H */
|
||||
|
53
minix/llvm/include/common/util/util_def.h
Normal file
53
minix/llvm/include/common/util/util_def.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU 1
|
||||
#endif
|
||||
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX 108
|
||||
#endif
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef MIN_MMAP_ADDR
|
||||
#define MIN_MMAP_ADDR ((void*)(PAGE_SIZE*100))
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_PRINTF
|
||||
#define _UTIL_PRINTF printf
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_PTHREAD_CREATE
|
||||
#define _UTIL_PTHREAD_CREATE pthread_create
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_PTHREAD_JOIN
|
||||
#define _UTIL_PTHREAD_JOIN pthread_join
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_PTHREAD_CANCEL
|
||||
#define _UTIL_PTHREAD_CANCEL pthread_cancel
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_PTHREAD_SIGMASK
|
||||
#define _UTIL_PTHREAD_SIGMASK pthread_sigmask
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_MALLOC
|
||||
#define _UTIL_MALLOC malloc
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_CALLOC
|
||||
#define _UTIL_CALLOC calloc
|
||||
#endif
|
||||
|
||||
#ifndef _UTIL_FREE
|
||||
#define _UTIL_FREE free
|
||||
#endif
|
||||
|
549
minix/llvm/include/magic_common.h
Normal file
549
minix/llvm/include/magic_common.h
Normal file
|
@ -0,0 +1,549 @@
|
|||
#ifndef _MAGIC_COMMON_H
|
||||
#define _MAGIC_COMMON_H
|
||||
|
||||
/* Magic constants. */
|
||||
#define MAGIC_PREFIX magic_
|
||||
#define MAGIC_PREFIX_STR "magic_"
|
||||
#define MAGIC_ASR_PREFIX magic_asr_
|
||||
#define MAGIC_ASR_PREFIX_STR "magic_asr_"
|
||||
#define MAGIC_EVAL_FUNC_PREFIX "me_"
|
||||
#define MAGIC_ANON_MEMBER_PREFIX "magic.anon"
|
||||
#define MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(S) \
|
||||
((S).startswith(MAGIC_HIDDEN_ARRAY_PREFIX) \
|
||||
|| (S).startswith(MAGIC_HIDDEN_STR_PREFIX))
|
||||
|
||||
#define MAGIC_VOID_PTR _____magic_instr_void_ptr
|
||||
#define MAGIC_VOID_PTR_NAME "_____magic_instr_void_ptr"
|
||||
#define MAGIC_VOID_ARRAY _____magic_instr_void_arr
|
||||
#define MAGIC_VOID_ARRAY_NAME "_____magic_instr_void_arr"
|
||||
|
||||
#define MAGIC_VOID_PTR_TYPE _magic_void_ptr_type_ptr
|
||||
#define MAGIC_VOID_PTR_TYPE_ID 1
|
||||
#define MAGIC_VOID_PTR_INT_CAST_TYPE _magic_void_ptr_int_cast_type_ptr
|
||||
#define MAGIC_VOID_PTR_INT_CAST_TYPE_ID 2
|
||||
#define MAGIC_VOID_ARRAY_TYPE _magic_void_array_type_ptr
|
||||
#define MAGIC_VOID_ARRAY_TYPE_ID 3
|
||||
#define MAGIC_PTRINT_TYPE _magic_ptrint_type_ptr
|
||||
#define MAGIC_PTRINT_TYPE_ID 4
|
||||
#define MAGIC_PTRINT_ARRAY_TYPE _magic_ptrint_array_type_ptr
|
||||
#define MAGIC_PTRINT_ARRAY_TYPE_ID 5
|
||||
#define MAGIC_VOID_TYPE (MAGIC_VOID_PTR_TYPE->contained_types[0])
|
||||
|
||||
#ifdef __MINIX
|
||||
#define GLOBAL_VARS_IN_SECTION 1
|
||||
#else
|
||||
#define GLOBAL_VARS_IN_SECTION 0
|
||||
#endif
|
||||
#define GLOBAL_VARS_SECTION_PREFIX ".gvars"
|
||||
#define GLOBAL_VARS_SECTION_DATA GLOBAL_VARS_SECTION_PREFIX
|
||||
#define GLOBAL_VARS_SECTION_RO (GLOBAL_VARS_SECTION_PREFIX "_ro")
|
||||
|
||||
#define MAGIC_LLVM_METADATA_SECTION "llvm.metadata"
|
||||
#define MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX "^.lib.*"
|
||||
#define MAGIC_STATIC_FUNCTIONS_SECTION "magic_functions"
|
||||
|
||||
#define MAGIC_STATIC_VARS_SECTION_PREFIX "magic_data"
|
||||
#define MAGIC_STATIC_VARS_SECTION_DATA MAGIC_STATIC_VARS_SECTION_PREFIX
|
||||
#define MAGIC_STATIC_VARS_SECTION_RO (MAGIC_STATIC_VARS_SECTION_PREFIX "_ro")
|
||||
|
||||
#define MAGIC_SHADOW_VARS_SECTION_PREFIX "magic_shadow_data"
|
||||
#define MAGIC_SHADOW_VARS_SECTION_DATA MAGIC_SHADOW_VARS_SECTION_PREFIX
|
||||
#define MAGIC_SHADOW_VARS_SECTION_RO (MAGIC_SHADOW_VARS_SECTION_PREFIX "_ro")
|
||||
|
||||
#define UNBL_SECTION_PREFIX "unblockify"
|
||||
#define MAGIC_SHADOW_VAR_PREFIX ".magic_shadow_"
|
||||
#define MAGIC_HIDDEN_ARRAY_PREFIX ".arr.magic"
|
||||
#define MAGIC_HIDDEN_STR_PREFIX ".str.magic"
|
||||
|
||||
/* Magic configuration. */
|
||||
#ifndef MAGIC_OUTPUT_CTL
|
||||
#define MAGIC_OUTPUT_CTL 0
|
||||
#endif
|
||||
/* 0=disabled, 1=force no debug output, 2=force no output (for perf. testing).*/
|
||||
#define MAGIC_CHECK_LEVEL 1
|
||||
/* 2=extra checks, 1=standard checks, 0=no checks (for perf. testing). */
|
||||
#define MAGIC_FLATTEN_FUNCTION_ARGS 1
|
||||
#define MAGIC_CHECK_INVARIANTS 1
|
||||
#define MAGIC_SHRINK_TYPE_STR 1
|
||||
#define MAGIC_MAX_NAME_LEN 64
|
||||
#define MAGIC_MAX_TYPE_STR_LEN 256
|
||||
#define MAGIC_MAX_RECURSIVE_TYPES 1024
|
||||
#define MAGIC_TYPE_STR_PRINT_MAX 5000
|
||||
#define MAGIC_TYPE_STR_PRINT_MAX_LEVEL 10
|
||||
#define MAGIC_MAX_DEAD_DSENTRIES 10
|
||||
#define MAGIC_MAX_DEAD_DSENTRIES_SIZE (1024 * 4 * 10)
|
||||
#define MAGIC_NAMED_ALLOC_USE_DBG_INFO 0
|
||||
/* 1=for more verbose dsentry naming. */
|
||||
#define MAGIC_FORCE_ALLOC_EXT_NAMES 0
|
||||
/* 1=to force external names for allocations made inside library functions. */
|
||||
#define MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE 0
|
||||
/* 0=to resort to void* type when a local external type is not supported. */
|
||||
#ifndef MAGIC_MEM_USAGE_OUTPUT_CTL
|
||||
#define MAGIC_MEM_USAGE_OUTPUT_CTL 0
|
||||
#endif
|
||||
/* 0=disabled, 1=use call site info 2=use stacktrace */
|
||||
|
||||
#define MAGIC_INSTRUMENT_MEM_FUNCS_ASR_ONLY 0
|
||||
#define MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS 1
|
||||
#define MAGIC_INSTRUMENT_MEM_FUNCS 1
|
||||
#define MAGIC_INSTRUMENT_STACK 1
|
||||
#define MAGIC_FORCE_RAW_UNIONS 0
|
||||
#define MAGIC_FORCE_RAW_BITFIELDS 0
|
||||
#define MAGIC_FORCE_DYN_MEM_ZERO_INIT 0
|
||||
/* 1=for accurate dsentry analysis. */
|
||||
#define MAGIC_INDEX_DYN_LIBS 1
|
||||
#define MAGIC_USE_DYN_MEM_WRAPPERS 1
|
||||
#define MAGIC_USE_DYN_DL_WRAPPERS 1
|
||||
#define MAGIC_ALLOW_DYN_MEM_WRAPPER_NESTING 1
|
||||
|
||||
/* qprof-related settings */
|
||||
#ifdef __MINIX
|
||||
#define MAGIC_USE_QPROF_INSTRUMENTATION 0
|
||||
#else
|
||||
#define MAGIC_USE_QPROF_INSTRUMENTATION 1
|
||||
#endif
|
||||
#define MAGIC_DEEPEST_LL_LOOP_HOOK magic_deepest_ll_loop
|
||||
#define MAGIC_DEEPEST_LL_LIB_HOOK magic_deepest_ll_lib
|
||||
#define MAGIC_DEEPEST_LL_LOOP_HOOK_NAME "magic_deepest_ll_loop"
|
||||
#define MAGIC_DEEPEST_LL_LIB_HOOK_NAME "magic_deepest_ll_lib"
|
||||
#define MAGIC_NUM_LL_TASK_CLASSES magic_num_ll_task_classes
|
||||
#define MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES magic_num_ll_block_ext_task_classes
|
||||
#define MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES magic_num_ll_block_int_task_classes
|
||||
#define MAGIC_NUM_LL_BLOCK_EXT_LIBS magic_num_ll_block_ext_libs
|
||||
#define MAGIC_NUM_LL_BLOCK_INT_LIBS magic_num_ll_block_int_libs
|
||||
#define MAGIC_NUM_LL_TASK_CLASSES_NAME "magic_num_ll_task_classes"
|
||||
#define MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME "magic_num_ll_block_ext_task_classes"
|
||||
#define MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME "magic_num_ll_block_int_task_classes"
|
||||
#define MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME "magic_num_ll_block_ext_libs"
|
||||
#define MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME "magic_num_ll_block_int_libs"
|
||||
|
||||
#define MAGIC_THREAD_SAFE 1
|
||||
#define MAGIC_FORCE_LOCKS 0
|
||||
#define MAGIC_LOOKUP_SENTRY 1
|
||||
#define MAGIC_LOOKUP_DSENTRY 1
|
||||
#define MAGIC_LOOKUP_FUNCTION 1
|
||||
#define MAGIC_LOOKUP_DFUNCTION 1
|
||||
#define MAGIC_LOOKUP_TYPE 1
|
||||
#define MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 1
|
||||
#define MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 1
|
||||
#define MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH 1
|
||||
|
||||
#define MAGIC_INDEX_INT_CAST 1
|
||||
#define MAGIC_INDEX_FUN_PTR_INT_CAST 1
|
||||
#define MAGIC_INDEX_STR_PTR_INT_CAST 1
|
||||
#define MAGIC_INDEX_VOID_PTR_INT_CAST 1
|
||||
#define MAGIC_INDEX_OTH_PTR_INT_CAST 1
|
||||
|
||||
#define MAGIC_INDEX_BIT_CAST 1
|
||||
#define MAGIC_INDEX_TRANSITIVE_BIT_CASTS 0
|
||||
#define MAGIC_INDEX_FUN_PTR_BIT_CAST 1
|
||||
#define MAGIC_INDEX_STR_PTR_BIT_CAST 1
|
||||
#define MAGIC_INDEX_VOID_PTR_BIT_CAST 0
|
||||
#define MAGIC_INDEX_OTH_PTR_BIT_CAST 1
|
||||
|
||||
#ifdef __MINIX
|
||||
#define MAGIC_SKIP_TOVOID_PTR_BIT_CAST 0
|
||||
#else
|
||||
#define MAGIC_SKIP_TOVOID_PTR_BIT_CAST 1
|
||||
#endif
|
||||
|
||||
#define MAGIC_COMPACT_COMP_TYPES 0
|
||||
|
||||
#define MAGIC_OFF_BY_N_PROTECTION_N 0
|
||||
|
||||
#define MAGIC_VARSIZED_STRUCTS_SUPPORT 1
|
||||
|
||||
#define MAGIC_ALLOW_DEAD_DSENTRIES_DEFAULT 0
|
||||
|
||||
#define MAGIC_WALK_UNIONS_AS_VOID_ARRAYS_DEFAULT 1
|
||||
|
||||
#define MAGIC_DEBUG_SELECT(D,ND) (MAGIC_OUTPUT_CTL>=1 ? (ND) : (D))
|
||||
#define MAGIC_OUTPUT_SELECT(D,ND,NO) \
|
||||
(MAGIC_OUTPUT_CTL>=2 ? (NO) : MAGIC_DEBUG_SELECT(D,ND))
|
||||
#define MAGIC_DEBUG_SET(D) MAGIC_DEBUG_SELECT(D,0)
|
||||
|
||||
#define MAGIC_ENABLED "_magic_enabled"
|
||||
|
||||
#define MAGIC_ARRAY_NAME "_magic_sentries_array"
|
||||
#define MAGIC_TYPE_ARRAY_NAME "_magic_types_array"
|
||||
#define MAGIC_FUNC_ARRAY_NAME "_magic_functions_array"
|
||||
#define MAGIC_DSINDEX_ARRAY_NAME "_magic_dsindexes_array"
|
||||
|
||||
#define MAGIC_ROOT_VAR_NAME "_magic_vars_buff"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_SEED "asr_seed"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE "asr_heap_map_do_permutate"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET "asr_heap_max_offset"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING "asr_heap_max_padding"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES "asr_map_max_offset_pages"
|
||||
#define MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES "asr_map_max_padding_pages"
|
||||
#define MAGIC_RSTRUCT_FIELD_TYPES "types"
|
||||
#define MAGIC_RSTRUCT_FIELD_TYPES_NUM "types_num"
|
||||
#define MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID "types_next_id"
|
||||
#define MAGIC_RSTRUCT_FIELD_FUNCTIONS "functions"
|
||||
#define MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM "functions_num"
|
||||
#define MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID "functions_next_id"
|
||||
#define MAGIC_RSTRUCT_FIELD_SENTRIES "sentries"
|
||||
#define MAGIC_RSTRUCT_FIELD_SENTRIES_NUM "sentries_num"
|
||||
#define MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM "sentries_str_num"
|
||||
#define MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID "sentries_next_id"
|
||||
#define MAGIC_RSTRUCT_FIELD_DSINDEXES "dsindexes"
|
||||
#define MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM "dsindexes_num"
|
||||
#define MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY "first_dsentry"
|
||||
#define MAGIC_RSTRUCT_FIELDS \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_SEED, \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAP_DO_PERMUTATE, \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_OFFSET, \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_HEAP_MAX_PADDING, \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_OFFSET_PAGES, \
|
||||
MAGIC_RSTRUCT_FIELD_ASR_MAP_MAX_PADDING_PAGES, \
|
||||
MAGIC_RSTRUCT_FIELD_TYPES, \
|
||||
MAGIC_RSTRUCT_FIELD_TYPES_NUM, \
|
||||
MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID, \
|
||||
MAGIC_RSTRUCT_FIELD_FUNCTIONS, \
|
||||
MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM, \
|
||||
MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID, \
|
||||
MAGIC_RSTRUCT_FIELD_SENTRIES, \
|
||||
MAGIC_RSTRUCT_FIELD_SENTRIES_NUM, \
|
||||
MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM, \
|
||||
MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID, \
|
||||
MAGIC_RSTRUCT_FIELD_DSINDEXES, \
|
||||
MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM, \
|
||||
MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY
|
||||
|
||||
#define MAGIC_ENTRY_POINT "main"
|
||||
#define MAGIC_INIT_FUNC_NAME "magic_init"
|
||||
#define MAGIC_DATA_INIT_FUNC_NAME "magic_data_init"
|
||||
|
||||
#define MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME "magic_stack_dsentries_create"
|
||||
#define MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME "magic_stack_dsentries_destroy"
|
||||
|
||||
#define MAGIC_GET_PAGE_SIZE_FUNC_NAME "magic_get_sys_pagesize"
|
||||
|
||||
#define MAGIC_VOID_PTR_TYPE_PTR_NAME "_magic_void_ptr_type_ptr"
|
||||
|
||||
#define MAGIC_ALLOC_NAME_SUFFIX "#"
|
||||
#define MAGIC_ALLOC_NAME_SEP "%"
|
||||
#define MAGIC_ALLOC_NONAME "%UNKNOWN"
|
||||
#define MAGIC_ALLOC_EXT_NAME "%EXT"
|
||||
#define MAGIC_ALLOC_EXT_PARENT_NAME "%EXT_PARENT"
|
||||
#define MAGIC_ALLOC_RET_ADDR_NAME "%RET_ADDR"
|
||||
#define MAGIC_ALLOC_INITIAL_STACK_NAME "%INITIAL_STACK_AREA"
|
||||
#define MAGIC_OBDSENTRY_DEFAULT_PARENT_NAME "%OUT_OF_BAND_PARENT"
|
||||
#define MAGIC_DSENTRY_DATA_SEGMENT_NAME "%LIB_DATA_SEGMENT"
|
||||
#define MAGIC_DSENTRY_ABS_NAME_SEP "~"
|
||||
#define MAGIC_SELEMENT_SEP "/"
|
||||
#define MAGIC_NAME_INVALID "%INVALID"
|
||||
|
||||
#define MAGIC_SSTRUCT_FIELD_ID "id"
|
||||
#define MAGIC_SSTRUCT_FIELD_NAME "name"
|
||||
#define MAGIC_SSTRUCT_FIELD_TYPE "type"
|
||||
#define MAGIC_SSTRUCT_FIELD_FLAGS "flags"
|
||||
#define MAGIC_SSTRUCT_FIELD_ADDRESS "address"
|
||||
#define MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS "shadow_address"
|
||||
#define MAGIC_SSTRUCT_FIELDS \
|
||||
MAGIC_SSTRUCT_FIELD_ID, \
|
||||
MAGIC_SSTRUCT_FIELD_NAME, \
|
||||
MAGIC_SSTRUCT_FIELD_TYPE, \
|
||||
MAGIC_SSTRUCT_FIELD_FLAGS, \
|
||||
MAGIC_SSTRUCT_FIELD_ADDRESS, \
|
||||
MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS
|
||||
|
||||
#define MAGIC_TSTRUCT_FIELD_ID "id"
|
||||
#define MAGIC_TSTRUCT_FIELD_NAME "name"
|
||||
#define MAGIC_TSTRUCT_FIELD_NAMES "names"
|
||||
#define MAGIC_TSTRUCT_FIELD_NUM_NAMES "num_names"
|
||||
#define MAGIC_TSTRUCT_FIELD_TYPE_STR "type_str"
|
||||
#define MAGIC_TSTRUCT_FIELD_SIZE "size"
|
||||
#define MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES "num_child_types"
|
||||
#define MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES "contained_types"
|
||||
#define MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES "compatible_types"
|
||||
#define MAGIC_TSTRUCT_FIELD_MEMBER_NAMES "member_names"
|
||||
#define MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS "member_offsets"
|
||||
#define MAGIC_TSTRUCT_FIELD_VALUE_SET "value_set"
|
||||
#define MAGIC_TSTRUCT_FIELD_TYPE_ID "type_id"
|
||||
#define MAGIC_TSTRUCT_FIELD_FLAGS "flags"
|
||||
#define MAGIC_TSTRUCT_FIELD_BIT_WIDTH "bit_width"
|
||||
#define MAGIC_TSTRUCT_FIELDS \
|
||||
MAGIC_TSTRUCT_FIELD_ID, \
|
||||
MAGIC_TSTRUCT_FIELD_NAME, \
|
||||
MAGIC_TSTRUCT_FIELD_NAMES, \
|
||||
MAGIC_TSTRUCT_FIELD_NUM_NAMES, \
|
||||
MAGIC_TSTRUCT_FIELD_TYPE_STR, \
|
||||
MAGIC_TSTRUCT_FIELD_SIZE, \
|
||||
MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES, \
|
||||
MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES, \
|
||||
MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES, \
|
||||
MAGIC_TSTRUCT_FIELD_MEMBER_NAMES, \
|
||||
MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS, \
|
||||
MAGIC_TSTRUCT_FIELD_VALUE_SET, \
|
||||
MAGIC_TSTRUCT_FIELD_TYPE_ID, \
|
||||
MAGIC_TSTRUCT_FIELD_FLAGS, \
|
||||
MAGIC_TSTRUCT_FIELD_BIT_WIDTH
|
||||
|
||||
#define MAGIC_FSTRUCT_FIELD_ID "id"
|
||||
#define MAGIC_FSTRUCT_FIELD_NAME "name"
|
||||
#define MAGIC_FSTRUCT_FIELD_TYPE "type"
|
||||
#define MAGIC_FSTRUCT_FIELD_FLAGS "flags"
|
||||
#define MAGIC_FSTRUCT_FIELD_ADDRESS "address"
|
||||
#define MAGIC_FSTRUCT_FIELDS \
|
||||
MAGIC_FSTRUCT_FIELD_ID, \
|
||||
MAGIC_FSTRUCT_FIELD_NAME, \
|
||||
MAGIC_FSTRUCT_FIELD_TYPE, \
|
||||
MAGIC_FSTRUCT_FIELD_FLAGS, \
|
||||
MAGIC_FSTRUCT_FIELD_ADDRESS
|
||||
|
||||
#define MAGIC_DSTRUCT_FIELD_TYPE "type"
|
||||
#define MAGIC_DSTRUCT_FIELD_NAME "name"
|
||||
#define MAGIC_DSTRUCT_FIELD_PARENT_NAME "parent_name"
|
||||
#define MAGIC_DSTRUCT_FIELD_FLAGS "flags"
|
||||
#define MAGIC_DSTRUCT_FIELDS \
|
||||
MAGIC_DSTRUCT_FIELD_TYPE, \
|
||||
MAGIC_DSTRUCT_FIELD_NAME, \
|
||||
MAGIC_DSTRUCT_FIELD_PARENT_NAME, \
|
||||
MAGIC_DSTRUCT_FIELD_FLAGS
|
||||
|
||||
#define MAGIC_TYPE_ISUNION 0x01
|
||||
#define MAGIC_TYPE_ISPADDED 0x02
|
||||
|
||||
/* Type IDs. */
|
||||
#define MAGIC_TYPE_VOID 1
|
||||
#define MAGIC_TYPE_FLOAT 2
|
||||
#define MAGIC_TYPE_INTEGER 3
|
||||
#define MAGIC_TYPE_FUNCTION 4
|
||||
#define MAGIC_TYPE_ARRAY 5
|
||||
#define MAGIC_TYPE_ENUM 6
|
||||
#define MAGIC_TYPE_VECTOR 7
|
||||
#define MAGIC_TYPE_UNION 8
|
||||
#define MAGIC_TYPE_STRUCT 9
|
||||
#define MAGIC_TYPE_POINTER 10
|
||||
#define MAGIC_TYPE_OPAQUE 11
|
||||
|
||||
/* Type flags. */
|
||||
#define MAGIC_TYPE_EXTERNAL 0x001
|
||||
#define MAGIC_TYPE_IS_ROOT 0x002
|
||||
#define MAGIC_TYPE_DYNAMIC 0x004
|
||||
#define MAGIC_TYPE_INT_CAST 0x008
|
||||
#define MAGIC_TYPE_STRICT_VALUE_SET 0x010
|
||||
#define MAGIC_TYPE_VARSIZE 0x020
|
||||
#define MAGIC_TYPE_UNSIGNED 0x040
|
||||
#define MAGIC_TYPE_NO_INNER_PTRS 0x080
|
||||
|
||||
/* State flags for sentries and functions. */
|
||||
#define MAGIC_STATE_DIRTY 0x00000001
|
||||
#define MAGIC_STATE_CONSTANT 0x00000002
|
||||
#define MAGIC_STATE_DYNAMIC 0x00000004
|
||||
#define MAGIC_STATE_DETACHED 0x00000008
|
||||
#define MAGIC_STATE_DATA 0x00000010
|
||||
#define MAGIC_STATE_HEAP 0x00000020
|
||||
#define MAGIC_STATE_MAP 0x00000040
|
||||
#define MAGIC_STATE_SHM 0x00000080
|
||||
#define MAGIC_STATE_STACK 0x00000100
|
||||
#define MAGIC_STATE_TEXT 0x00000200
|
||||
/* All libraries. */
|
||||
#define MAGIC_STATE_LIB 0x00000400
|
||||
/* Dynamically linked libraries. */
|
||||
#define MAGIC_STATE_LIB_SO 0x00000800
|
||||
/* Dynamically loaded libraries. */
|
||||
#define MAGIC_STATE_LIB_DSO 0x00001000
|
||||
#define MAGIC_STATE_ADDR_NOT_TAKEN 0x00002000
|
||||
#define MAGIC_STATE_EXT 0x00004000
|
||||
#define MAGIC_STATE_OUT_OF_BAND 0x00008000
|
||||
#define MAGIC_STATE_STRING 0x00010000
|
||||
#define MAGIC_STATE_NAMED_STRING 0x00020000
|
||||
#define MAGIC_STATE_MODE_R 0x00040000
|
||||
#define MAGIC_STATE_MODE_W 0x00080000
|
||||
#define MAGIC_STATE_MODE_X 0x00100000
|
||||
#define MAGIC_STATE_THREAD_LOCAL 0x00200000
|
||||
#define MAGIC_STATE_MEMPOOL 0x00400000
|
||||
#define MAGIC_STATE_MEMBLOCK 0x00800000
|
||||
#define MAGIC_STATE_EXTERNAL 0x01000000
|
||||
#define MAGIC_STATE_TYPE_SIZE_MISMATCH 0x02000000
|
||||
#define MAGIC_STATE_IMMUTABLE 0x04000000
|
||||
#define MAGIC_STATE_INIT 0x08000000
|
||||
#define MAGIC_STATE_DIRTY_PAGE 0x10000000
|
||||
/* Skip char* and void* entries in arrays */
|
||||
#define MAGIC_STATE_SKIP_BYTE_INDICES 0x20000000
|
||||
|
||||
#define MAGIC_STATE_ANNOTATION_MASK \
|
||||
(MAGIC_STATE_MODE_R | MAGIC_STATE_MODE_W | MAGIC_STATE_MODE_X)
|
||||
|
||||
#define MAGIC_ASR_FLAG_INIT 0x40000
|
||||
|
||||
#define MAGIC_STATE_EXTF_MASK 0xFF000000
|
||||
#define MAGIC_STATE_EXTF_SHIFT 24
|
||||
|
||||
#define MAGIC_STATE_FLAG(E,F) (((E)->flags & (F)) != 0)
|
||||
#define MAGIC_STATE_FLAGS(E,F) (((E)->flags & (F)) == (F))
|
||||
#define MAGIC_STATE_FLAGS_REGION(F) \
|
||||
((F) & (MAGIC_STATE_DATA | MAGIC_STATE_HEAP | MAGIC_STATE_MAP \
|
||||
| MAGIC_STATE_SHM | MAGIC_STATE_STACK | MAGIC_STATE_TEXT))
|
||||
#define MAGIC_STATE_FLAGS_LIBSPEC(F) \
|
||||
((F) & (MAGIC_STATE_LIB | MAGIC_STATE_LIB_SO | MAGIC_STATE_LIB_DSO))
|
||||
#define MAGIC_STATE_REGION(E) MAGIC_STATE_FLAGS_REGION((E)->flags)
|
||||
#define MAGIC_STATE_LIBSPEC(E) MAGIC_STATE_FLAGS_LIBSPEC((E)->flags)
|
||||
#define MAGIC_STATE_FLAGS_REGION_C(F) \
|
||||
(((F) & MAGIC_STATE_DATA) ? 'D' : ((F) & MAGIC_STATE_HEAP) ? 'H' \
|
||||
: ((F) & MAGIC_STATE_SHM) ? 'X' : ((F) & MAGIC_STATE_MAP) ? 'M' \
|
||||
: ((F) & MAGIC_STATE_STACK) ? 'S' : ((F) & MAGIC_STATE_TEXT) ? 'T' : '?')
|
||||
#define MAGIC_STATE_FLAGS_LIBSPEC_C(F) \
|
||||
(((F) & MAGIC_STATE_LIB) ? (((F) & MAGIC_STATE_LIB_SO) ? 'l' \
|
||||
: ((F) & MAGIC_STATE_LIB_DSO) ? 'o' : 'L') : '0')
|
||||
#define MAGIC_STATE_REGION_C(E) MAGIC_STATE_FLAGS_REGION_C((E)->flags)
|
||||
#define MAGIC_STATE_LIBSPEC_C(E) MAGIC_STATE_FLAGS_LIBSPEC_C((E)->flags)
|
||||
|
||||
#define MAGIC_STATE_IS_EXTF(F) (((F) & MAGIC_STATE_EXTF_MASK) == (F))
|
||||
#define MAGIC_STATE_FLAGS_TO_EXTF(F) \
|
||||
(((F) & MAGIC_STATE_EXTF_MASK) >> MAGIC_STATE_EXTF_SHIFT)
|
||||
#define MAGIC_STATE_FLAGS_TO_NONEXTF(F) ((F) & (~MAGIC_STATE_EXTF_MASK))
|
||||
#define MAGIC_STATE_EXTF_TO_FLAGS(F) \
|
||||
(((F) << MAGIC_STATE_EXTF_SHIFT) & MAGIC_STATE_EXTF_MASK)
|
||||
#define MAGIC_STATE_EXTF_FLAG(E,F) (MAGIC_STATE_EXTF_GET(E,F) != 0)
|
||||
#define MAGIC_STATE_EXTF_GET(E,F) \
|
||||
((MAGIC_STATE_FLAGS_TO_EXTF((E)->flags) & (F)))
|
||||
#define MAGIC_STATE_EXTF_ADD(E,F) \
|
||||
((E)->flags |= MAGIC_STATE_EXTF_TO_FLAGS(F))
|
||||
#define MAGIC_STATE_EXTF_DEL(E,F) \
|
||||
((E)->flags &= ~MAGIC_STATE_EXTF_TO_FLAGS(F))
|
||||
#define MAGIC_STATE_EXTF_SET(E,F) \
|
||||
do { \
|
||||
MAGIC_STATE_EXTF_CLEAR(E); \
|
||||
(E)->flags |= MAGIC_STATE_EXTF_TO_FLAGS(F); \
|
||||
} while(0)
|
||||
#define MAGIC_STATE_EXTF_CLEAR(E) ((E)->flags &= ~MAGIC_STATE_EXTF_MASK)
|
||||
|
||||
/* Annotations. */
|
||||
#define MAGIC_CALL_ANNOTATION_VAR _magic_call_annotation_var
|
||||
#define MAGIC_CALL_ANNOTATION_VAR_NAME "_magic_call_annotation_var"
|
||||
#define MAGIC_CALL_ANNOTATE(C, VALUE) \
|
||||
do { C; MAGIC_CALL_ANNOTATION_VAR = VALUE; } while(0)
|
||||
#define MAGIC_CALL_MEM_SKIP_INSTRUMENTATION 0x01
|
||||
|
||||
#define MAGIC_VAR_ANNOTATION_PREFIX_NAME "_magic_var_annotation_"
|
||||
|
||||
#define MAGIC_VAR_ANNOTATE(T,V,A) \
|
||||
T V; \
|
||||
volatile int _magic_var_annotation_ ## V = A
|
||||
#define MAGIC_VAR_INIT_ANNOTATE(T,V,I,A) \
|
||||
T V = I; \
|
||||
volatile int _magic_var_annotation_ ## V = A
|
||||
|
||||
#define MAGIC_MEMCPY_FUNC_NAME "memcpy"
|
||||
#define MAGIC_MALLOC_FUNC_NAME "malloc"
|
||||
|
||||
/* Magic memory pool management functions. */
|
||||
#define MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME \
|
||||
"mempool_block_alloc_template"
|
||||
|
||||
/* Wrapper functions. */
|
||||
#define MAGIC_MEMPOOL_CREATE_FUNCS \
|
||||
__X(magic_mempool_create_begin), __X(magic_mempool_create_end)
|
||||
#define MAGIC_MEMPOOL_DESTROY_FUNCS \
|
||||
__X(magic_mempool_destroy_begin), __X(magic_mempool_destroy_end)
|
||||
#define MAGIC_MEMPOOL_MGMT_FUNCS \
|
||||
__X(magic_mempool_mgmt_begin), __X(magic_mempool_mgmt_end)
|
||||
#define MAGIC_MEMPOOL_RESET_FUNCS \
|
||||
__X(magic_mempool_reset_begin), __X(magic_mempool_mgmt_end)
|
||||
#define MAGIC_MEMPOOL_FUNCS \
|
||||
MAGIC_MEMPOOL_CREATE_FUNCS, \
|
||||
MAGIC_MEMPOOL_DESTROY_FUNCS, \
|
||||
MAGIC_MEMPOOL_MGMT_FUNCS, \
|
||||
MAGIC_MEMPOOL_RESET_FUNCS
|
||||
|
||||
#define MAGIC_MEMPOOL_CREATE_FUNC_NAMES MAGIC_MEMPOOL_CREATE_FUNCS, ""
|
||||
#define MAGIC_MEMPOOL_DESTROY_FUNC_NAMES MAGIC_MEMPOOL_DESTROY_FUNCS, ""
|
||||
#define MAGIC_MEMPOOL_MGMT_FUNC_NAMES MAGIC_MEMPOOL_MGMT_FUNCS, ""
|
||||
#define MAGIC_MEMPOOL_RESET_FUNC_NAMES MAGIC_MEMPOOL_RESET_FUNCS, ""
|
||||
#define MAGIC_MEMPOOL_FUNC_NAMES MAGIC_MEMPOOL_FUNCS, ""
|
||||
|
||||
/* Flags for inlining wrapper calls. */
|
||||
#define MAGIC_PRE_HOOK_SIMPLE_CALL 0x0001
|
||||
#define MAGIC_PRE_HOOK_FORWARDING_CALL 0x0002
|
||||
#define MAGIC_POST_HOOK_SIMPLE_CALL 0x0004
|
||||
#define MAGIC_POST_HOOK_FORWARDING_CALL 0x0008
|
||||
#define MAGIC_PRE_HOOK_DEBUG 0x0010
|
||||
#define MAGIC_POST_HOOK_DEBUG 0x0020
|
||||
#define MAGIC_PRE_HOOK_FLAGS_MASK \
|
||||
(MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_PRE_HOOK_FORWARDING_CALL)
|
||||
#define MAGIC_POST_HOOK_FLAGS_MASK \
|
||||
(MAGIC_POST_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL)
|
||||
#define MAGIC_HOOK_DEBUG_MASK \
|
||||
(MAGIC_PRE_HOOK_DEBUG | MAGIC_POST_HOOK_DEBUG)
|
||||
|
||||
#if (MAGIC_MEM_USAGE_OUTPUT_CTL == 1)
|
||||
#define MAGIC_MEMPOOL_CREATE_FUNC_FLAGS MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL | MAGIC_PRE_HOOK_DEBUG
|
||||
#else
|
||||
#define MAGIC_MEMPOOL_CREATE_FUNC_FLAGS MAGIC_PRE_HOOK_SIMPLE_CALL | MAGIC_POST_HOOK_FORWARDING_CALL
|
||||
#endif
|
||||
#define MAGIC_MEMPOOL_DESTROY_FUNC_FLAGS \
|
||||
MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
|
||||
#define MAGIC_MEMPOOL_MGMT_FUNC_FLAGS \
|
||||
MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
|
||||
#define MAGIC_MEMPOOL_RESET_FUNC_FLAGS \
|
||||
MAGIC_PRE_HOOK_FORWARDING_CALL | MAGIC_POST_HOOK_SIMPLE_CALL
|
||||
#define MAGIC_MEMPOOL_FUNC_FLAGS \
|
||||
MAGIC_MEMPOOL_CREATE_FUNC_FLAGS, \
|
||||
MAGIC_MEMPOOL_DESTROY_FUNC_FLAGS, \
|
||||
MAGIC_MEMPOOL_MGMT_FUNC_FLAGS, \
|
||||
MAGIC_MEMPOOL_RESET_FUNC_FLAGS
|
||||
|
||||
#define MAGIC_CHECKPOINT_ENABLED "_magic_checkpoint_enabled"
|
||||
#define MAGIC_CHECKPOINT_FUNC_NAME "sef_receive_status"
|
||||
|
||||
#define MAGIC_SHADOW_FUNC_PREFIX "llvm_shadow"
|
||||
|
||||
#define MAGIC_LAZY_CHECKPOINT_ENABLED "_magic_lazy_checkpoint_enabled"
|
||||
#define MAGIC_LAZY_CHECKPOINT_CLEARDF_FUNC_NAME "sef_receive_status"
|
||||
|
||||
#define MAGIC_LAZY_CHECKPOINT_SHADOW_TAG "llvm_shadow"
|
||||
|
||||
/* Magic memory functions. */
|
||||
#define MAGIC_MEMA_FUNCS \
|
||||
__X(malloc), __X(calloc), __X(realloc), \
|
||||
__X(posix_memalign), __X(valloc), __X(memalign), \
|
||||
__X(mmap), \
|
||||
__X(brk), __X(sbrk), \
|
||||
__X(shmat), \
|
||||
__X(mmap64)
|
||||
#define MAGIC_MEMA_FUNC_ALLOC_FLAGS \
|
||||
MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
|
||||
MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
|
||||
MAGIC_STATE_MAP, \
|
||||
MAGIC_STATE_HEAP, MAGIC_STATE_HEAP, \
|
||||
MAGIC_STATE_SHM, \
|
||||
MAGIC_STATE_MAP
|
||||
|
||||
#ifdef __MINIX
|
||||
#define MAGIC_MEMA_EXTRA_FUNCS , __X(vm_map_cacheblock)
|
||||
#define MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS , MAGIC_STATE_MAP
|
||||
#else
|
||||
#define MAGIC_MEMA_EXTRA_FUNCS
|
||||
#define MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS
|
||||
#endif
|
||||
|
||||
#define MAGIC_MEMD_FUNCS \
|
||||
__X(free), __X(munmap), __X(shmdt)
|
||||
#define MAGIC_MEMD_FUNC_ALLOC_FLAGS \
|
||||
0, 0, 0
|
||||
|
||||
#define MAGIC_MEM_FUNCS MAGIC_MEMA_FUNCS MAGIC_MEMA_EXTRA_FUNCS, MAGIC_MEMD_FUNCS
|
||||
#define MAGIC_MEM_UNS_FUNCS \
|
||||
__X(mmap2), __X(remap_file_pages), __X(mremap)
|
||||
#define MAGIC_MEM_FUNC_ALLOC_FLAGS \
|
||||
MAGIC_MEMA_FUNC_ALLOC_FLAGS MAGIC_MEMA_EXTRA_FUNC_ALLOC_FLAGS, MAGIC_MEMD_FUNC_ALLOC_FLAGS
|
||||
|
||||
#define MAGIC_DL_FUNCS \
|
||||
__X(dlopen), __X(dlclose)
|
||||
|
||||
#define MAGIC_MEMA_FUNC_NAMES MAGIC_MEMA_FUNCS MAGIC_MEMA_EXTRA_FUNCS, ""
|
||||
#define MAGIC_MEMD_FUNC_NAMES MAGIC_MEMD_FUNCS, ""
|
||||
#define MAGIC_MEM_FUNC_NAMES MAGIC_MEM_FUNCS, ""
|
||||
#define MAGIC_DL_FUNC_NAMES MAGIC_DL_FUNCS, ""
|
||||
|
||||
#if MAGIC_INSTRUMENT_MEM_FUNCS_ASR_ONLY
|
||||
#define MAGIC_MEM_PREFIX_STRS MAGIC_ASR_PREFIX_STR, MAGIC_PREFIX_STR, ""
|
||||
#else
|
||||
#define MAGIC_MEM_PREFIX_STRS MAGIC_PREFIX_STR, ""
|
||||
#endif
|
||||
|
||||
#endif /* _MAGIC_COMMON_H */
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "pass_hello.h"
|
||||
#include <pass.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
|
|
@ -1,224 +0,0 @@
|
|||
#ifndef _PASS_HELLO_H
|
||||
#define _PASS_HELLO_H
|
||||
|
||||
#if LLVM_VERSION >= 33
|
||||
#define ATTRIBUTE_SET_TY AttributeSet
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/Type.h>
|
||||
#include <llvm/IR/Constants.h>
|
||||
#include <llvm/IR/Intrinsics.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/LLVMContext.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
#include <llvm/IR/DataLayout.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#else /* LLVM_VERSION < 33 */
|
||||
#define ATTRIBUTE_SET_TY AttrListPtr
|
||||
#include <llvm/Function.h>
|
||||
#include <llvm/Module.h>
|
||||
#include <llvm/Instructions.h>
|
||||
#include <llvm/Type.h>
|
||||
#include <llvm/Constants.h>
|
||||
#include <llvm/Intrinsics.h>
|
||||
#include <llvm/DerivedTypes.h>
|
||||
#include <llvm/LLVMContext.h>
|
||||
#include <llvm/IntrinsicInst.h>
|
||||
#endif /* LLVM_VERSION >= 33 */
|
||||
|
||||
#if LLVM_VERSION >= 32
|
||||
#define DATA_LAYOUT_TY DataLayout
|
||||
#define ATTRIBUTE_SET_RET_IDX ATTRIBUTE_SET_TY::ReturnIndex
|
||||
#define ATTRIBUTE_SET_FN_IDX ATTRIBUTE_SET_TY::FunctionIndex
|
||||
#include <llvm/DebugInfo.h>
|
||||
#if LLVM_VERSION == 32
|
||||
#include <llvm/DataLayout.h>
|
||||
#include <llvm/IRBuilder.h>
|
||||
#endif
|
||||
#else /* LLVM_VERSION < 32 */
|
||||
#define DATA_LAYOUT_TY TargetData
|
||||
#define ATTRIBUTE_SET_RET_IDX 0
|
||||
#define ATTRIBUTE_SET_FN_IDX (~0U)
|
||||
#include <llvm/Target/TargetData.h>
|
||||
#include <llvm/Analysis/DebugInfo.h>
|
||||
#include <llvm/Support/IRBuilder.h>
|
||||
#endif /* LLVM_VERSION >= 32 */
|
||||
|
||||
#if LLVM_VERSION >= 31
|
||||
/* XXX Check. */
|
||||
#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray
|
||||
|
||||
#else /* LLVM_VERSION < 31 */
|
||||
#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray
|
||||
#endif /* LLVM_VERSION >= 31 */
|
||||
|
||||
#if LLVM_VERSION >= 30
|
||||
#define BASE_PARSER parser
|
||||
|
||||
#define TYPECONST
|
||||
#else /* LLVM_VERSION < 30 */
|
||||
#define BASE_PARSER basic_parser
|
||||
|
||||
#define TYPECONST const
|
||||
#endif /* LLVM_VERSION >= 30 */
|
||||
|
||||
#if LLVM_VERSION >= 29
|
||||
#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy
|
||||
#else /* LLVM_VERSION < 29 */
|
||||
#define VALUE_TO_VALUE_MAP_TY ValueMap<const Value*, Value*>
|
||||
#endif /* LLVM_VERSION >= 29 */
|
||||
|
||||
#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10))
|
||||
#define VOID_PTR_TY(M) PointerType::get(IntegerType::get((M).getContext(), 8), 0)
|
||||
#define VOID_PTR_PTR_TY(M) PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0)
|
||||
|
||||
#define DEBUG_LLVM_DEBUG_API 0
|
||||
|
||||
typedef enum PassUtilLinkageTypeE {
|
||||
PASS_UTIL_LINKAGE_NONE = 0,
|
||||
PASS_UTIL_LINKAGE_WEAK,
|
||||
PASS_UTIL_LINKAGE_COMMON,
|
||||
PASS_UTIL_LINKAGE_EXTERNAL,
|
||||
PASS_UTIL_LINKAGE_EXTERNAL_WEAK,
|
||||
PASS_UTIL_LINKAGE_WEAK_POINTER,
|
||||
PASS_UTIL_LINKAGE_PRIVATE,
|
||||
__NUM_PASS_UTIL_LINKAGE_TYPES
|
||||
/* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/
|
||||
} PassUtilLinkageType;
|
||||
|
||||
#define PASS_UTIL_LINKAGE_TYPE_STRINGS \
|
||||
"NONE", \
|
||||
"WEAK", \
|
||||
"COMMON", \
|
||||
"EXTERNAL", \
|
||||
"EXTERNAL_WEAK", \
|
||||
"WEAK_POINTER", \
|
||||
"PRIVATE"
|
||||
|
||||
typedef enum PassUtilPropE {
|
||||
PASS_UTIL_PROP_NONE,
|
||||
PASS_UTIL_PROP_NOINLINE,
|
||||
PASS_UTIL_PROP_USED,
|
||||
PASS_UTIL_PROP_PRESERVE,
|
||||
__NUM_PASS_UTIL_PROPS
|
||||
} PassUtilProp;
|
||||
|
||||
#define PASS_UTIL_FLAG(F) (1 << F)
|
||||
|
||||
#define PASS_COMMON_INIT_ONCE() \
|
||||
Module *PassUtil::M = NULL; \
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class PassUtil {
|
||||
public:
|
||||
static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
|
||||
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
|
||||
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
|
||||
static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
|
||||
static Constant* getStringConstantArray(Module &M, const std::string &string);
|
||||
static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
|
||||
private:
|
||||
static Module *M;
|
||||
};
|
||||
|
||||
inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
|
||||
#if LLVM_VERSION >= 30
|
||||
ArrayRef<Value*> ref(indexes);
|
||||
return ConstantExpr::getGetElementPtr(constant, ref);
|
||||
#else
|
||||
return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
|
||||
#if LLVM_VERSION >= 30
|
||||
ArrayRef<Value*> ref(args);
|
||||
return CallInst::Create(F, ref, NameStr, InsertBefore);
|
||||
#else
|
||||
return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
|
||||
#if LLVM_VERSION >= 30
|
||||
ArrayRef<Value*> ref(args);
|
||||
return CallInst::Create(F, ref, NameStr, InsertAtEnd);
|
||||
#else
|
||||
return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg)
|
||||
{
|
||||
#if LLVM_VERSION >= 30
|
||||
ArrayRef<TYPECONST Type*> ref(argsTy);
|
||||
return FunctionType::get(Result, ref, isVarArg);
|
||||
#else
|
||||
return FunctionType::get(Result, argsTy, isVarArg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string)
|
||||
{
|
||||
std::vector<Constant*> elements;
|
||||
elements.reserve(string.size() + 1);
|
||||
for (unsigned i = 0; i < string.size(); ++i)
|
||||
elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i]));
|
||||
|
||||
// Add a null terminator to the string...
|
||||
elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0));
|
||||
|
||||
ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size());
|
||||
return ConstantArray::get(ATy, elements);
|
||||
}
|
||||
|
||||
inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable)
|
||||
{
|
||||
static std::map<std::string, GlobalVariable*> stringCache;
|
||||
std::map<std::string, GlobalVariable*>::iterator stringCacheIt;
|
||||
std::string stringCacheKey;
|
||||
GlobalVariable *strGV = NULL;
|
||||
|
||||
if (cacheable) {
|
||||
stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection;
|
||||
stringCacheIt = stringCache.find(stringCacheKey);
|
||||
if (stringCacheIt != stringCache.end()) {
|
||||
strGV = stringCacheIt->second;
|
||||
cacheable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strGV) {
|
||||
//create a constant internal string reference
|
||||
Constant *stringValue = PassUtil::getStringConstantArray(M, string);
|
||||
|
||||
//create the global variable, cache it, and record it in the module
|
||||
strGV = new GlobalVariable(M, stringValue->getType(), true,
|
||||
GlobalValue::InternalLinkage, stringValue, varName);
|
||||
if (varSection.compare("")) {
|
||||
strGV->setSection(varSection);
|
||||
}
|
||||
}
|
||||
if (getElementPtrExpr) {
|
||||
std::vector<Value*> strConstantIndices;
|
||||
strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
|
||||
strConstantIndices.push_back(ZERO_CONSTANT_INT(M));
|
||||
*getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices);
|
||||
}
|
||||
|
||||
if (cacheable) {
|
||||
stringCache.insert(std::pair<std::string, GlobalVariable*>(stringCacheKey, strGV));
|
||||
}
|
||||
|
||||
return strGV;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* _PASS_HELLO_H */
|
1011
minix/llvm/passes/include/common/pass_common.h
Normal file
1011
minix/llvm/passes/include/common/pass_common.h
Normal file
File diff suppressed because it is too large
Load diff
569
minix/llvm/passes/include/common/qprof_common.h
Normal file
569
minix/llvm/passes/include/common/qprof_common.h
Normal file
|
@ -0,0 +1,569 @@
|
|||
#ifndef _QPROF_COMMON_H
|
||||
#define _QPROF_COMMON_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <common/util/stdlib.h>
|
||||
|
||||
#define QPROF_SEP ","
|
||||
#define QPROF_SEP2 ":"
|
||||
#define QPROF_SEP3 "|"
|
||||
|
||||
#define QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR) \
|
||||
static cl::opt<std::string> \
|
||||
VAR(#P "-ll-sitestacks", \
|
||||
cl::desc("Specify all the long-lived sitestacks on a per-task basis in qprof format"), \
|
||||
cl::init(""), cl::NotHidden, cl::ValueRequired)
|
||||
|
||||
#define QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR) \
|
||||
static cl::opt<std::string> \
|
||||
VAR(#P "-deepest-ll-loops", \
|
||||
cl::desc("Specify all the deepest long-lived loops on a per-task basis in qprof format"), \
|
||||
cl::init(""), cl::NotHidden, cl::ValueRequired)
|
||||
|
||||
#define QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR) \
|
||||
static cl::opt<std::string> \
|
||||
VAR(#P "-deepest-ll-libs", \
|
||||
cl::desc("Specify all the deepest long-lived loop lib calls on a per-task basis in qprof format"), \
|
||||
cl::init(""), cl::NotHidden, cl::ValueRequired)
|
||||
|
||||
#define QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR) \
|
||||
static cl::opt<std::string> \
|
||||
VAR(#P "-task-classes", \
|
||||
cl::desc("Specify all the task classes in qprof format"), \
|
||||
cl::init(""), cl::NotHidden, cl::ValueRequired)
|
||||
|
||||
#define QPROF_DECLARE_ALL_OPTS(P, VAR1, VAR2, VAR3, VAR4) \
|
||||
QPROF_DECLARE_LL_SITESTACKS_OPT(P, VAR1); \
|
||||
QPROF_DECLARE_DEEPEST_LL_LOOPS_OPT(P, VAR2); \
|
||||
QPROF_DECLARE_DEEPEST_LL_LIBS_OPT(P, VAR3); \
|
||||
QPROF_DECLARE_TASK_CLASSES_OPT(P, VAR4) \
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class QProfSite {
|
||||
public:
|
||||
static QProfSite* get(Module &M, int taskClassID, int taskSiteID, std::string moduleName, int lineNum, std::string functionName, std::string siteName, std::string siteFuncName, int siteDepth, int lib, unsigned long libFlags, bool refreshSite=true);
|
||||
static QProfSite* getFromString(Module &M, int taskClassID, int taskSiteID, std::string &siteString, bool refreshSite=true);
|
||||
static std::vector<QProfSite*> getFromSitesString(Module &M, std::string &sitesString, bool refreshSites=true);
|
||||
|
||||
void refresh(Module &M);
|
||||
std::string toString();
|
||||
bool isLoop();
|
||||
bool isFunction();
|
||||
bool isCallsite();
|
||||
bool isLibCallsite();
|
||||
bool equals(QProfSite *other);
|
||||
|
||||
int taskClassID;
|
||||
int taskSiteID;
|
||||
std::string moduleName;
|
||||
int lineNum;
|
||||
std::string functionName;
|
||||
std::string siteName;
|
||||
std::string siteFuncName;
|
||||
unsigned long libFlags;
|
||||
Function *function;
|
||||
Function *siteFunction;
|
||||
Instruction *siteInstruction;
|
||||
private:
|
||||
QProfSite() {}
|
||||
|
||||
int siteDepth;
|
||||
int lib;
|
||||
};
|
||||
|
||||
class QProfConf {
|
||||
public:
|
||||
static QProfConf* get(Module &M, std::string *llSitestacks, std::string *deepestLLLoops, std::string *deepestLLLibs, std::string *taskClasses, bool refreshSites=true);
|
||||
|
||||
std::map<int, std::vector<QProfSite*> > getTaskClassLLSitestacks();
|
||||
std::map<int, QProfSite*> getTaskClassDeepestLLLoops();
|
||||
std::map<int, std::vector<QProfSite*> > getTaskClassDeepestLLLibs();
|
||||
int getNumTaskClasses();
|
||||
int getNumLLTaskClasses();
|
||||
int getNumLLBlockExtTaskClasses();
|
||||
int getNumLLBlockIntTaskClasses();
|
||||
int getNumLLBlockExtLibs();
|
||||
int getNumLLBlockIntLibs();
|
||||
|
||||
std::vector<QProfSite*> getLLFunctions();
|
||||
std::vector<QProfSite*> getDeepestLLLoops();
|
||||
std::vector<QProfSite*> getDeepestLLLibs();
|
||||
bool lookupTaskClassLibFlags(int taskClassID, int *libFlags);
|
||||
void mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID);
|
||||
void mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID);
|
||||
void mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID);
|
||||
void mergeTaskClassPair(int taskClassID, int otherTaskClassID);
|
||||
void mergeAllTaskClassesWithSameDeepestLLLoops();
|
||||
void print(raw_ostream &O);
|
||||
void printSiteList(raw_ostream &O, std::vector<QProfSite*> &list);
|
||||
|
||||
private:
|
||||
QProfConf() {}
|
||||
|
||||
static std::map<int, std::vector<QProfSite*> > parseTaskClassSiteList(Module &M, std::string &str, bool refreshSites=true);
|
||||
static std::map<int, QProfSite*> parseTaskClassSite(Module &M, std::string &str, bool refreshSites=true);
|
||||
static std::vector<int> parseIntList(std::string &str);
|
||||
|
||||
std::map<int, std::vector<QProfSite*> > taskClassLLSitestacks;
|
||||
std::map<int, QProfSite*> taskClassDeepestLLLoops;
|
||||
std::map<int, std::vector<QProfSite*> > taskClassDeepestLLLibs;
|
||||
int numTaskClasses;
|
||||
int numLLTaskClasses;
|
||||
int numLLBlockExtTaskClasses;
|
||||
int numLLBlockIntTaskClasses;
|
||||
int numLLBlockExtLibs;
|
||||
int numLLBlockIntLibs;
|
||||
};
|
||||
|
||||
static int stringRefToInt(StringRef &ref)
|
||||
{
|
||||
return atoi(ref.str().c_str());
|
||||
}
|
||||
|
||||
inline QProfSite* QProfSite::get(Module &M, int taskClassID, int taskSiteID,
|
||||
std::string moduleName, int lineNum, std::string functionName,
|
||||
std::string siteName, std::string siteFuncName, int siteDepth, int lib,
|
||||
unsigned long libFlags, bool refreshSite)
|
||||
{
|
||||
QProfSite *site = new QProfSite();
|
||||
site->taskClassID = taskClassID;
|
||||
site->taskSiteID = taskSiteID;
|
||||
site->moduleName = moduleName;
|
||||
site->lineNum = lineNum;
|
||||
site->functionName = functionName;
|
||||
site->siteName = siteName;
|
||||
site->siteFuncName = siteFuncName;
|
||||
site->siteDepth = siteDepth;
|
||||
site->lib = lib;
|
||||
site->libFlags = libFlags;
|
||||
site->function = NULL;
|
||||
site->siteFunction = NULL;
|
||||
site->siteInstruction = NULL;
|
||||
if (refreshSite) {
|
||||
site->refresh(M);
|
||||
}
|
||||
|
||||
return site;
|
||||
}
|
||||
|
||||
inline QProfSite* QProfSite::getFromString(Module &M, int taskClassID, int taskSiteID,
|
||||
std::string &siteString, bool refreshSite)
|
||||
{
|
||||
StringRef ref(siteString);
|
||||
SmallVector< StringRef, 3 > tokenVector;
|
||||
if (!siteString.compare("")) {
|
||||
return NULL;
|
||||
}
|
||||
ref.split(tokenVector, QPROF_SEP3);
|
||||
assert(tokenVector.size() == 8);
|
||||
return get(M, taskClassID, taskSiteID, tokenVector[0], stringRefToInt(tokenVector[1]),
|
||||
tokenVector[2], tokenVector[3], tokenVector[4],
|
||||
stringRefToInt(tokenVector[5]), stringRefToInt(tokenVector[6]),
|
||||
stringRefToInt(tokenVector[7]), refreshSite);
|
||||
}
|
||||
|
||||
inline std::vector<QProfSite*> QProfSite::getFromSitesString(Module &M,
|
||||
std::string &sitesString, bool refreshSites)
|
||||
{
|
||||
unsigned i;
|
||||
int taskClassID;
|
||||
std::vector<QProfSite*> sites;
|
||||
StringRef ref(sitesString);
|
||||
SmallVector< StringRef, 3 > tokenVector;
|
||||
if (!sitesString.compare("")) {
|
||||
return sites;
|
||||
}
|
||||
ref.split(tokenVector, QPROF_SEP2);
|
||||
assert(tokenVector.size() > 1);
|
||||
taskClassID = stringRefToInt(tokenVector[0]);
|
||||
for (i=1;i<tokenVector.size();i++) {
|
||||
std::string token = tokenVector[i].str();
|
||||
QProfSite *site = QProfSite::getFromString(M, taskClassID, i, token,
|
||||
refreshSites);
|
||||
sites.push_back(site);
|
||||
}
|
||||
return sites;
|
||||
}
|
||||
|
||||
inline void QProfSite::refresh(Module &M)
|
||||
{
|
||||
BasicBlock *siteBB = NULL;
|
||||
function = NULL;
|
||||
siteFunction = NULL;
|
||||
siteInstruction = NULL;
|
||||
function = M.getFunction(functionName);
|
||||
siteFunction = M.getFunction(siteFuncName);
|
||||
if (!siteFunction) {
|
||||
errs() << "Function " << siteFuncName << " not found. Invalid qprof profiling data?\n";
|
||||
}
|
||||
assert(siteFunction);
|
||||
for (Function::iterator BB = siteFunction->begin(),
|
||||
e = siteFunction->end(); BB != e; ++BB) {
|
||||
if (!BB->getName().compare(siteName)) {
|
||||
siteBB = BB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(siteBB);
|
||||
if (isCallsite()) {
|
||||
for (BasicBlock::iterator it = siteBB->begin(); it != siteBB->end(); ++it) {
|
||||
CallSite CS(it);
|
||||
if (CS.getInstruction() && CS.getCalledFunction() == function) {
|
||||
siteInstruction = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(siteInstruction && "Invalid qprof callsite?");
|
||||
}
|
||||
else {
|
||||
siteInstruction = &siteBB->front();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string QProfSite::toString()
|
||||
{
|
||||
std::string str;
|
||||
raw_string_ostream ostream(str);
|
||||
ostream << taskClassID << QPROF_SEP3 << taskSiteID << QPROF_SEP3 << moduleName << QPROF_SEP3 << lineNum << QPROF_SEP3 << functionName << QPROF_SEP3 << siteName << QPROF_SEP3 << siteFuncName << QPROF_SEP3 << siteDepth << QPROF_SEP3 << lib << QPROF_SEP3 << libFlags;
|
||||
ostream.flush();
|
||||
return str;
|
||||
}
|
||||
|
||||
inline bool QProfSite::isLoop()
|
||||
{
|
||||
return siteDepth > 0;
|
||||
}
|
||||
|
||||
inline bool QProfSite::isFunction()
|
||||
{
|
||||
return !isLoop() && !isCallsite();
|
||||
}
|
||||
|
||||
inline bool QProfSite::isCallsite()
|
||||
{
|
||||
return isLibCallsite();
|
||||
}
|
||||
|
||||
inline bool QProfSite::isLibCallsite()
|
||||
{
|
||||
return lib != 0;
|
||||
}
|
||||
|
||||
inline bool QProfSite::equals(QProfSite *other)
|
||||
{
|
||||
if (lineNum != other->lineNum) {
|
||||
return false;
|
||||
}
|
||||
if (libFlags != other->libFlags) {
|
||||
return false;
|
||||
}
|
||||
if (moduleName.compare(other->moduleName)) {
|
||||
return false;
|
||||
}
|
||||
if (functionName.compare(other->functionName)) {
|
||||
return false;
|
||||
}
|
||||
if (siteName.compare(other->siteName)) {
|
||||
return false;
|
||||
}
|
||||
if (siteFuncName.compare(other->siteFuncName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline QProfConf* QProfConf::get(Module &M, std::string *llSitestacks,
|
||||
std::string *deepestLLLoops, std::string *deepestLLLibs,
|
||||
std::string *taskClasses, bool refreshSites)
|
||||
{
|
||||
std::vector<int> intValues;
|
||||
QProfConf *conf = new QProfConf();
|
||||
if (llSitestacks) {
|
||||
conf->taskClassLLSitestacks = parseTaskClassSiteList(M,
|
||||
*llSitestacks, refreshSites);
|
||||
}
|
||||
if (deepestLLLoops) {
|
||||
conf->taskClassDeepestLLLoops = parseTaskClassSite(M,
|
||||
*deepestLLLoops, refreshSites);
|
||||
}
|
||||
if (deepestLLLibs) {
|
||||
conf->taskClassDeepestLLLibs = parseTaskClassSiteList(M,
|
||||
*deepestLLLibs, refreshSites);
|
||||
}
|
||||
if (taskClasses) {
|
||||
intValues = parseIntList(*taskClasses);
|
||||
}
|
||||
if (intValues.size() > 0) {
|
||||
assert(intValues.size() == 6);
|
||||
conf->numTaskClasses = intValues[0];
|
||||
conf->numLLTaskClasses = intValues[1];
|
||||
conf->numLLBlockExtTaskClasses = intValues[2];
|
||||
conf->numLLBlockIntTaskClasses = intValues[3];
|
||||
conf->numLLBlockExtLibs = intValues[4];
|
||||
conf->numLLBlockIntLibs = intValues[5];
|
||||
}
|
||||
else {
|
||||
conf->numTaskClasses = 0;
|
||||
conf->numLLTaskClasses = 0;
|
||||
conf->numLLBlockExtTaskClasses = 0;
|
||||
conf->numLLBlockIntTaskClasses = 0;
|
||||
conf->numLLBlockExtLibs = 0;
|
||||
conf->numLLBlockIntLibs = 0;
|
||||
}
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassLLSitestacks()
|
||||
{
|
||||
return taskClassLLSitestacks;
|
||||
}
|
||||
|
||||
inline std::map<int, QProfSite*> QProfConf::getTaskClassDeepestLLLoops()
|
||||
{
|
||||
return taskClassDeepestLLLoops;
|
||||
}
|
||||
|
||||
inline std::map<int, std::vector<QProfSite*> > QProfConf::getTaskClassDeepestLLLibs()
|
||||
{
|
||||
return taskClassDeepestLLLibs;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumTaskClasses()
|
||||
{
|
||||
return numTaskClasses;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumLLTaskClasses()
|
||||
{
|
||||
return numLLTaskClasses;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumLLBlockExtTaskClasses()
|
||||
{
|
||||
return numLLBlockExtTaskClasses;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumLLBlockIntTaskClasses()
|
||||
{
|
||||
return numLLBlockIntTaskClasses;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumLLBlockExtLibs()
|
||||
{
|
||||
return numLLBlockExtLibs;
|
||||
}
|
||||
|
||||
inline int QProfConf::getNumLLBlockIntLibs()
|
||||
{
|
||||
return numLLBlockIntLibs;
|
||||
}
|
||||
|
||||
inline std::vector<QProfSite*> QProfConf::getLLFunctions()
|
||||
{
|
||||
std::vector<QProfSite*> sites;
|
||||
std::map<int, std::vector<QProfSite*> >::iterator it;
|
||||
it = taskClassLLSitestacks.begin();
|
||||
for (; it != taskClassLLSitestacks.end(); it++) {
|
||||
std::vector<QProfSite*> *siteVector = &it->second;
|
||||
for (unsigned i=0;i<siteVector->size();i++) {
|
||||
QProfSite* site = (*siteVector)[i];
|
||||
if (site->isFunction()) {
|
||||
sites.push_back((*siteVector)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sites;
|
||||
}
|
||||
|
||||
inline std::vector<QProfSite*> QProfConf::getDeepestLLLoops()
|
||||
{
|
||||
std::vector<QProfSite*> sites;
|
||||
std::map<int, QProfSite*>::iterator it;
|
||||
it = taskClassDeepestLLLoops.begin();
|
||||
for (; it != taskClassDeepestLLLoops.end(); it++) {
|
||||
sites.push_back(it->second);
|
||||
}
|
||||
return sites;
|
||||
}
|
||||
|
||||
inline std::vector<QProfSite*> QProfConf::getDeepestLLLibs()
|
||||
{
|
||||
std::vector<QProfSite*> sites;
|
||||
std::map<int, std::vector<QProfSite*> >::iterator it;
|
||||
it = taskClassDeepestLLLibs.begin();
|
||||
for (; it != taskClassDeepestLLLibs.end(); it++) {
|
||||
std::vector<QProfSite*> *siteVector = &it->second;
|
||||
for (unsigned i=0;i<siteVector->size();i++) {
|
||||
sites.push_back((*siteVector)[i]);
|
||||
}
|
||||
}
|
||||
return sites;
|
||||
}
|
||||
|
||||
inline bool QProfConf::lookupTaskClassLibFlags(int taskClassID, int *libFlags)
|
||||
{
|
||||
bool found = false;
|
||||
std::vector<QProfSite*> deepestLLLibs = getDeepestLLLibs();
|
||||
|
||||
*libFlags = 0;
|
||||
for (unsigned i=0;i<deepestLLLibs.size();i++) {
|
||||
QProfSite *site = deepestLLLibs[i];
|
||||
if (site->taskClassID == taskClassID) {
|
||||
*libFlags |= site->libFlags;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
inline void QProfConf::mergeTaskClassLLSitestacks(int taskClassID, int otherTaskClassID)
|
||||
{
|
||||
size_t erased = taskClassLLSitestacks.erase(otherTaskClassID);
|
||||
assert(erased == 1);
|
||||
}
|
||||
|
||||
inline void QProfConf::mergeTaskClassDeepestLLLoops(int taskClassID, int otherTaskClassID)
|
||||
{
|
||||
size_t erased = taskClassDeepestLLLoops.erase(otherTaskClassID);
|
||||
assert(erased == 1);
|
||||
}
|
||||
|
||||
inline void QProfConf::mergeTaskClassDeepestLLLibs(int taskClassID, int otherTaskClassID)
|
||||
{
|
||||
size_t erased = taskClassDeepestLLLibs.erase(otherTaskClassID);
|
||||
assert(erased == 1);
|
||||
}
|
||||
|
||||
inline void QProfConf::mergeTaskClassPair(int taskClassID,
|
||||
int otherTaskClassID)
|
||||
{
|
||||
int libFlags;
|
||||
mergeTaskClassLLSitestacks(taskClassID, otherTaskClassID);
|
||||
mergeTaskClassDeepestLLLoops(taskClassID, otherTaskClassID);
|
||||
mergeTaskClassDeepestLLLibs(taskClassID, otherTaskClassID);
|
||||
|
||||
numTaskClasses--;
|
||||
if (lookupTaskClassLibFlags(taskClassID, &libFlags)) {
|
||||
numLLTaskClasses--;
|
||||
if (libFlags & _UTIL_STLIB_FLAG(STLIB_BLOCK_EXT)) {
|
||||
numLLBlockExtTaskClasses--;
|
||||
}
|
||||
else {
|
||||
numLLBlockIntTaskClasses--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void QProfConf::mergeAllTaskClassesWithSameDeepestLLLoops()
|
||||
{
|
||||
std::vector<QProfSite*> deepestLLLoops = getDeepestLLLoops();
|
||||
std::vector<std::pair<QProfSite*, QProfSite*> > loopPairs;
|
||||
|
||||
for (unsigned i=0;i<deepestLLLoops.size();i++) {
|
||||
QProfSite *site = deepestLLLoops[i];
|
||||
for (unsigned j=0;j<i;j++) {
|
||||
if (site->equals(deepestLLLoops[j])) {
|
||||
loopPairs.push_back(std::pair<QProfSite*, QProfSite*>(site, deepestLLLoops[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i=0;i<loopPairs.size();i++) {
|
||||
int taskClassID = loopPairs[i].first->taskClassID;
|
||||
int otherTaskClassID = loopPairs[i].second->taskClassID;
|
||||
mergeTaskClassPair(taskClassID, otherTaskClassID);
|
||||
}
|
||||
}
|
||||
|
||||
inline void QProfConf::print(raw_ostream &O)
|
||||
{
|
||||
std::vector<QProfSite*> list;
|
||||
O << "*** QProfConf:\n";
|
||||
O << " - numTaskClasses=" << getNumTaskClasses() << "\n";
|
||||
O << " - numLLTaskClasses=" << getNumLLTaskClasses() << "\n";
|
||||
O << " - numLLBlockExtTaskClasses=" << getNumLLBlockExtTaskClasses() << "\n";
|
||||
O << " - numLLBlockIntTaskClasses=" << getNumLLBlockIntTaskClasses() << "\n";
|
||||
O << " - numLLBlockExtLibs=" << getNumLLBlockExtLibs() << "\n";
|
||||
O << " - numLLBlockIntLibs=" << getNumLLBlockIntLibs() << "\n";
|
||||
list = getLLFunctions();
|
||||
O << " - LLFunctions="; printSiteList(O, list); O << "\n";
|
||||
list = getDeepestLLLoops();
|
||||
O << " - deepestLLLoops="; printSiteList(O, list); O << "\n";
|
||||
list = getDeepestLLLibs();
|
||||
O << " - deepestLLLibs="; printSiteList(O, list); O << "\n";
|
||||
}
|
||||
|
||||
inline void QProfConf::printSiteList(raw_ostream &O, std::vector<QProfSite*> &list)
|
||||
{
|
||||
for (std::vector<QProfSite*>::iterator it = list.begin(); it != list.end(); it++) {
|
||||
QProfSite* site = *it;
|
||||
if (it != list.begin()) {
|
||||
O << ", ";
|
||||
}
|
||||
O << "{ ";
|
||||
O << site->toString();
|
||||
O << " }";
|
||||
}
|
||||
}
|
||||
|
||||
inline std::map<int, std::vector<QProfSite*> > QProfConf::parseTaskClassSiteList(Module &M,
|
||||
std::string &str, bool refreshSites)
|
||||
{
|
||||
std::map<int, std::vector<QProfSite*> > siteListMap;
|
||||
StringRef ref(str);
|
||||
SmallVector< StringRef, 3 > tokenVector;
|
||||
if (!str.compare("")) {
|
||||
return siteListMap;
|
||||
}
|
||||
ref.split(tokenVector, QPROF_SEP);
|
||||
for (unsigned i=0;i<tokenVector.size();i++) {
|
||||
std::string token = tokenVector[i].str();
|
||||
std::vector<QProfSite*> sites = QProfSite::getFromSitesString(M,
|
||||
token, refreshSites);
|
||||
if (sites.size() > 0) {
|
||||
int taskClassID = sites[0]->taskClassID;
|
||||
siteListMap.insert(std::pair<int, std::vector<QProfSite*> >(taskClassID,
|
||||
sites));
|
||||
}
|
||||
}
|
||||
return siteListMap;
|
||||
}
|
||||
|
||||
inline std::map<int, QProfSite*> QProfConf::parseTaskClassSite(Module &M,
|
||||
std::string &str, bool refreshSites)
|
||||
{
|
||||
std::map<int, std::vector<QProfSite*> >::iterator it;
|
||||
std::map<int, std::vector<QProfSite*> > siteListMap =
|
||||
parseTaskClassSiteList(M, str, refreshSites);
|
||||
std::map<int, QProfSite*> siteMap;
|
||||
for (it=siteListMap.begin();it!=siteListMap.end();it++) {
|
||||
std::vector<QProfSite*> list = it->second;
|
||||
assert(list.size() == 1);
|
||||
siteMap.insert(std::pair<int, QProfSite*>(it->first, list[0]));
|
||||
}
|
||||
|
||||
return siteMap;
|
||||
}
|
||||
|
||||
inline std::vector<int> QProfConf::parseIntList(std::string &str)
|
||||
{
|
||||
std::vector<int> intValues;
|
||||
StringRef ref(str);
|
||||
SmallVector< StringRef, 3 > tokenVector;
|
||||
if (!str.compare("")) {
|
||||
return intValues;
|
||||
}
|
||||
ref.split(tokenVector, QPROF_SEP);
|
||||
for (unsigned i=0;i<tokenVector.size();i++) {
|
||||
intValues.push_back(stringRefToInt(tokenVector[i]));
|
||||
}
|
||||
|
||||
return intValues;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* _QPROF_COMMON_H */
|
32
minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h
Normal file
32
minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef MAGIC_CTLAZY_CHECKPOINT_PASS_H
|
||||
#define MAGIC_CTLAZY_CHECKPOINT_PASS_H
|
||||
|
||||
#include <magic/magic.h>
|
||||
#include <magic/MagicPass.h>
|
||||
#include <magic/support/VariableRefs.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define magicCTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicCTLazyCheckpointPass: " << M << "\n")
|
||||
|
||||
class MagicCTLazyCheckpointPass : public FunctionPass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
MagicCTLazyCheckpointPass();
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA;
|
||||
|
||||
bool instructionModifiesVar(Module &M, Instruction *inst, GlobalVariable* var);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
minix/llvm/passes/include/magic/MagicCheckpointPass.h
Normal file
29
minix/llvm/passes/include/magic/MagicCheckpointPass.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef MAGIC_CHECKPOINT_PASS_H
|
||||
#define MAGIC_CHECKPOINT_PASS_H
|
||||
|
||||
#include <magic/magic.h>
|
||||
#include <magic/MagicPass.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define magicCheckpointPassLog(M) DEBUG(dbgs() << "MagicCheckpointPass: " << M << "\n")
|
||||
|
||||
class MagicCheckpointPass : public ModulePass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
MagicCheckpointPass();
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual bool runOnModule(Module &M);
|
||||
|
||||
private:
|
||||
MagicPass *MP;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h
Normal file
29
minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef MAGIC_LTLAZY_CHECKPOINT_PASS_H
|
||||
#define MAGIC_LTLAZY_CHECKPOINT_PASS_H
|
||||
|
||||
#include <magic/magic.h>
|
||||
#include <magic/MagicPass.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define magicLTLazyCheckpointPassLog(M) DEBUG(dbgs() << "MagicLTLazyCheckpointPass: " << M << "\n")
|
||||
|
||||
class MagicLTLazyCheckpointPass : public FunctionPass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
MagicLTLazyCheckpointPass();
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
private:
|
||||
MagicPass *MP;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
137
minix/llvm/passes/include/magic/MagicPass.h
Normal file
137
minix/llvm/passes/include/magic/MagicPass.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#ifndef MAGIC_PASS_H
|
||||
|
||||
#define MAGIC_PASS_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic/magic.h>
|
||||
#include <magic/support/Backports.h>
|
||||
#include <magic/support/MagicUtil.h>
|
||||
#include <magic/support/SmartType.h>
|
||||
#include <magic/support/TypeInfo.h>
|
||||
#include <magic/support/MagicDebugFunction.h>
|
||||
#include <magic/support/MagicMemFunction.h>
|
||||
#include <magic/support/MagicMmapCtlFunction.h>
|
||||
|
||||
#if MAGIC_USE_QPROF_INSTRUMENTATION
|
||||
#include <common/qprof_common.h>
|
||||
#endif
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define magicPassLog(M) DEBUG(dbgs() << "MagicPass: " << M << "\n")
|
||||
#define magicPassErr(M) errs() << "MagicPass: " << M << "\n"
|
||||
|
||||
class MagicPass : public ModulePass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
MagicPass();
|
||||
|
||||
std::vector<GlobalVariable*> getGlobalVariables() const;
|
||||
std::vector<int> getGlobalVariableSizes() const;
|
||||
std::vector<GlobalVariable*> getShadowGlobalVariables() const;
|
||||
std::vector<Function*> getFunctions() const;
|
||||
GlobalVariable* getMagicArray() const;
|
||||
GlobalVariable* getMagicTypeArray() const;
|
||||
GlobalVariable* getMagicFunctionArray() const;
|
||||
GlobalVariable* getMagicDsindexArray() const;
|
||||
|
||||
virtual bool runOnModule(Module &M);
|
||||
|
||||
private:
|
||||
std::vector<GlobalVariable*> globalVariables;
|
||||
std::set<GlobalVariable*> globalVariablesWithAddressTaken;
|
||||
std::vector<int> globalVariableSizes;
|
||||
std::vector<GlobalVariable*> shadowGlobalVariables;
|
||||
std::vector<Function*> functions;
|
||||
std::vector<TypeInfo*> globalTypeInfos;
|
||||
std::map<GlobalValue*, TypeInfo*> globalParentMap;
|
||||
std::map<GlobalValue*, TypeInfo*>::iterator parentMapIt;
|
||||
std::map<std::string, GlobalVariable*> stringOwnerMap;
|
||||
std::map<std::string, GlobalVariable*>::iterator stringOwnerMapIt;
|
||||
std::map<GlobalVariable*, std::string> stringOwnerInvertedMap;
|
||||
std::map<GlobalVariable*, std::string>::iterator stringOwnerInvertedMapIt;
|
||||
|
||||
GlobalVariable* magicArray;
|
||||
GlobalVariable* magicTypeArray;
|
||||
GlobalVariable* magicFunctionArray;
|
||||
GlobalVariable* magicDsindexArray;
|
||||
|
||||
std::vector<std::string> libPathRegexes;
|
||||
std::vector<std::string> voidTypeAliases;
|
||||
std::set<std::string> voidTypeAliasesSet;
|
||||
std::vector<std::string> mmFuncPrefixes;
|
||||
std::set<std::pair<std::string, std::string> > mmFuncPairs;
|
||||
std::vector<std::string> mmPoolFunctions;
|
||||
std::vector<std::string> mmapCtlFunctions;
|
||||
std::set<std::string>::iterator stringSetIt;
|
||||
std::set<Function*> brkFunctions;
|
||||
std::set<Function*> sbrkFunctions;
|
||||
std::vector<Regex*> magicDataSectionRegexes;
|
||||
std::vector<Regex*> magicFunctionSectionRegexes;
|
||||
std::vector<Regex*> extLibSectionRegexes;
|
||||
|
||||
#if MAGIC_USE_QPROF_INSTRUMENTATION
|
||||
QProfConf *qprofConf;
|
||||
#endif
|
||||
|
||||
void qprofInstrumentationInit(Module &M);
|
||||
void qprofInstrumentationApply(Module &M);
|
||||
bool checkPointerVariableIndexes(TYPECONST Type* type, std::vector<int> &ptrVarIndexes, unsigned offset=0);
|
||||
void findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent = NULL, bool isUser=false);
|
||||
TypeInfo* typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName);
|
||||
TypeInfo* getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName);
|
||||
TypeInfo* fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos);
|
||||
TypeInfo* fillExternalTypeInfos(TYPECONST Type* sourceType, GlobalValue *parent, std::vector<TypeInfo*> &typeInfos);
|
||||
void printInterestingTypes(TYPECONST TypeInfo *aTypeInfo);
|
||||
unsigned getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo);
|
||||
FunctionType* getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs);
|
||||
bool isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType);
|
||||
void indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitcastMap);
|
||||
|
||||
void fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction);
|
||||
void indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap);
|
||||
void addMagicStackDsentryFuncCalls(Module &M, Function *insertCallsInFunc, Function *localsFromFunc, Function *dsentryCreateFunc, Function *dsentryDestroyFunc, TYPECONST StructType *dsentryStructType, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap, std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo, std::vector<TypeInfo*> &typeInfoList, std::vector<std::pair<std::string, std::string> > &namesList, std::vector<int> &flagsList);
|
||||
bool isExtLibrary(GlobalValue *GV, DIDescriptor *DID);
|
||||
bool isMagicGV(Module &M, GlobalVariable *GV);
|
||||
bool isMagicFunction(Module &M, Function *F);
|
||||
};
|
||||
|
||||
inline std::vector<GlobalVariable*> MagicPass::getGlobalVariables() const {
|
||||
return globalVariables;
|
||||
}
|
||||
|
||||
inline std::vector<int> MagicPass::getGlobalVariableSizes() const {
|
||||
return globalVariableSizes;
|
||||
}
|
||||
|
||||
inline std::vector<GlobalVariable*> MagicPass::getShadowGlobalVariables() const {
|
||||
return shadowGlobalVariables;
|
||||
}
|
||||
|
||||
inline std::vector<Function*> MagicPass::getFunctions() const {
|
||||
return functions;
|
||||
}
|
||||
|
||||
inline GlobalVariable* MagicPass::getMagicArray() const {
|
||||
return magicArray;
|
||||
}
|
||||
|
||||
inline GlobalVariable* MagicPass::getMagicTypeArray() const {
|
||||
return magicTypeArray;
|
||||
}
|
||||
|
||||
inline GlobalVariable* MagicPass::getMagicFunctionArray() const {
|
||||
return magicFunctionArray;
|
||||
}
|
||||
|
||||
inline GlobalVariable* MagicPass::getMagicDsindexArray() const {
|
||||
return magicDsindexArray;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
11
minix/llvm/passes/include/magic/magic.h
Normal file
11
minix/llvm/passes/include/magic/magic.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _MAGIC_PASS_H
|
||||
#define _MAGIC_PASS_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic_common.h>
|
||||
|
||||
#define MAGIC_FORCE_ALIGN 0
|
||||
#define MAGIC_FORCE_INLINING 0
|
||||
|
||||
#endif /* _MAGIC_PASS_H */
|
||||
|
24
minix/llvm/passes/include/magic/support/Backports.h
Normal file
24
minix/llvm/passes/include/magic/support/Backports.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef BACKPORTS_H
|
||||
#define BACKPORTS_H
|
||||
|
||||
#include <pass.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Backports {
|
||||
public:
|
||||
|
||||
//From DbgInfoPrinter.cpp (LLVM 2.9)
|
||||
static Value *findDbgGlobalDeclare(GlobalVariable *V);
|
||||
static Value *findDbgSubprogramDeclare(Function *V);
|
||||
static const DbgDeclareInst *findDbgDeclare(const Value *V);
|
||||
|
||||
//From Local.cpp (LLVM 2.9)
|
||||
static DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
117
minix/llvm/passes/include/magic/support/BitFieldAggregation.h
Normal file
117
minix/llvm/passes/include/magic/support/BitFieldAggregation.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
#ifndef BIT_FIELD_AGGREGATION_H
|
||||
#define BIT_FIELD_AGGREGATION_H
|
||||
|
||||
#include <magic/support/EDIType.h>
|
||||
#include <magic/support/TypeUtil.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define BitFieldAggregationErr(M) errs() << "BitFieldAggregation: " << M << "\n"
|
||||
|
||||
#define BFA_NAME_PREFIX "__BFA__"
|
||||
|
||||
class BitFieldAggregation {
|
||||
public:
|
||||
BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
|
||||
BitFieldAggregation();
|
||||
void init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter);
|
||||
|
||||
const std::string getDescription() const;
|
||||
|
||||
unsigned getTypeIndex() const;
|
||||
unsigned getEDITypeIndex() const;
|
||||
std::string getName() const;
|
||||
std::vector<DIDerivedType> getMembers() const;
|
||||
|
||||
unsigned getSize() const;
|
||||
TYPECONST Type *getType() const;
|
||||
std::vector<EDIType> getEDITypes() const;
|
||||
unsigned getRepresentativeEDITypeIndex() const;
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
static bool getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError=false);
|
||||
static bool hasBitFields(TYPECONST Type *type, const EDIType *aEDIType);
|
||||
static bool isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx);
|
||||
|
||||
private:
|
||||
TYPECONST Type *type;
|
||||
std::vector<EDIType> EDITypes;
|
||||
unsigned typeIndex;
|
||||
unsigned EDITypeIndex;
|
||||
std::string name;
|
||||
std::vector<DIDerivedType> members;
|
||||
unsigned size;
|
||||
|
||||
static std::string bfaNamePrefix;
|
||||
|
||||
static BitFieldAggregation* getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter);
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const BitFieldAggregation &bfa) {
|
||||
bfa.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline unsigned BitFieldAggregation::getTypeIndex() const {
|
||||
return typeIndex;
|
||||
}
|
||||
|
||||
inline unsigned BitFieldAggregation::getEDITypeIndex() const {
|
||||
return EDITypeIndex;
|
||||
}
|
||||
|
||||
inline std::string BitFieldAggregation::getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::vector<DIDerivedType> BitFieldAggregation::getMembers() const {
|
||||
return members;
|
||||
}
|
||||
|
||||
inline unsigned BitFieldAggregation::getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
inline TYPECONST Type *BitFieldAggregation::getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
inline std::vector<EDIType> BitFieldAggregation::getEDITypes() const {
|
||||
return EDITypes;
|
||||
}
|
||||
|
||||
inline unsigned BitFieldAggregation::getRepresentativeEDITypeIndex() const {
|
||||
return EDITypeIndex;
|
||||
}
|
||||
|
||||
inline void BitFieldAggregation::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
inline bool BitFieldAggregation::hasBitFields(TYPECONST Type *type, const EDIType *aEDIType) {
|
||||
if(!aEDIType->isStructTy()) {
|
||||
return false;
|
||||
}
|
||||
unsigned numContainedTypes = aEDIType->getNumContainedTypes();
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if (isBitField(type, aEDIType, i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool BitFieldAggregation::isBitField(TYPECONST Type *type, const EDIType *aEDIType, unsigned memberIdx) {
|
||||
const DIDerivedType subDIType = aEDIType->getMember(memberIdx);
|
||||
unsigned EDITypeBits = subDIType.getSizeInBits();
|
||||
const DIType aDIType = PassUtil::getDITypeDerivedFrom(subDIType);
|
||||
unsigned EDITypeOriginalBits = aDIType.getSizeInBits();
|
||||
return (EDITypeBits>0 && EDITypeOriginalBits>0 && EDITypeBits != EDITypeOriginalBits);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
274
minix/llvm/passes/include/magic/support/EDIType.h
Normal file
274
minix/llvm/passes/include/magic/support/EDIType.h
Normal file
|
@ -0,0 +1,274 @@
|
|||
#ifndef EDITYPE_H
|
||||
#define EDITYPE_H
|
||||
|
||||
#include <pass.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define EDITypeLog(M) DEBUG(dbgs() << "EDIType: " << M << "\n")
|
||||
#define EDITypeErr(M) errs() << "EDIType: " << M << "\n"
|
||||
|
||||
#define EDIType_assert(X) do { \
|
||||
if(!(X)) { \
|
||||
errs() << "Assertion failed, dumping object...\n"; \
|
||||
errs() << *this; \
|
||||
} \
|
||||
assert(X); \
|
||||
} while(0)
|
||||
|
||||
class EDIType {
|
||||
public:
|
||||
EDIType(const MDNode *N, bool norm=true, bool checkOpaqueTypes=true);
|
||||
EDIType(bool norm=false, bool checkOpaqueTypes=false);
|
||||
EDIType(const DIType aDIType, bool norm=true, bool checkOpaqueTypes=true);
|
||||
|
||||
bool operator == (const EDIType& aEDIType) const;
|
||||
|
||||
static const bool NORMALIZE = true;
|
||||
static const bool DO_NOT_NORMALIZE = false;
|
||||
static const bool CHECK_OPAQUE_TYPES = true;
|
||||
static const bool DO_NOT_CHECK_OPAQUE_TYPES = false;
|
||||
|
||||
const std::string getDescription(int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
|
||||
const EDIType& getContainedType(unsigned i, bool norm=true) const;
|
||||
unsigned getNumContainedTypes() const;
|
||||
const DIDerivedType& getMember(unsigned i) const;
|
||||
bool isUnionOrStructTy(bool isStruct=true, bool isUnion=true) const;
|
||||
bool hasInnerPointers() const;
|
||||
DIArray getTypeArray() const;
|
||||
const EDIType* getTopStructType(unsigned index) const;
|
||||
|
||||
unsigned getNumElements() const;
|
||||
unsigned getNumDimensions() const;
|
||||
void setCurrentDimension(unsigned dimension);
|
||||
unsigned getCurrentDimension() const;
|
||||
const DIType *getDIType() const;
|
||||
StringRef getName() const;
|
||||
std::vector<StringRef> getNames() const;
|
||||
StringRef getNamesString() const;
|
||||
std::vector<unsigned> getEnumValues() const;
|
||||
unsigned getTag()const;
|
||||
EDIType getTypeDerivedFrom() const;
|
||||
bool isType() const;
|
||||
bool isBasicType() const;
|
||||
bool isDerivedType() const;
|
||||
bool isCompositeType() const;
|
||||
bool isPrimitiveType() const;
|
||||
bool isAggregateType() const;
|
||||
bool isVoidTy() const;
|
||||
bool isComplexFloatingPointTy() const;
|
||||
bool isFloatingPointTy() const;
|
||||
bool isCharTy() const;
|
||||
bool isIntTy() const;
|
||||
bool isBoolTy() const;
|
||||
bool isIntegerTy() const;
|
||||
bool isFunctionTy() const;
|
||||
bool isArrayTy() const;
|
||||
bool isEnumTy() const;
|
||||
bool isVectorTy() const;
|
||||
bool isUnionTy() const;
|
||||
bool isStructTy() const;
|
||||
bool isPointerTy() const;
|
||||
bool isOpaqueTy() const;
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void printDescription(raw_ostream &OS, int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
|
||||
bool equals(const EDIType *other) const;
|
||||
|
||||
static std::string lookupTypedefName(std::string &name);
|
||||
static std::string lookupUnionMemberName(TYPECONST Type* type);
|
||||
static const EDIType* getStructEDITypeByName(std::string &name);
|
||||
static void setModule(Module *M);
|
||||
static void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
|
||||
|
||||
private:
|
||||
DIType aDIType;
|
||||
unsigned currentDimension;
|
||||
bool checkOpaqueTypes;
|
||||
StringRef myName;
|
||||
std::vector<StringRef> myNames;
|
||||
static StringRef voidName;
|
||||
static Module *module;
|
||||
static DebugInfoFinder DIFinder;
|
||||
|
||||
void init(bool norm, bool checkOpaqueTypes);
|
||||
void normalize();
|
||||
void normalizeTypedef();
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const EDIType &aEDIType) {
|
||||
aEDIType.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline unsigned EDIType::getNumElements() const {
|
||||
if(!isArrayTy() && !isVectorTy()) {
|
||||
return 1;
|
||||
}
|
||||
const DIArray aDIArray = getTypeArray();
|
||||
const DIDescriptor aDIDescriptor = aDIArray.getElement(currentDimension);
|
||||
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_subrange_type);
|
||||
|
||||
return PassUtil::getDbgSubrangeNumElements((DISubrange)aDIDescriptor);
|
||||
}
|
||||
|
||||
inline unsigned EDIType::getNumDimensions() const {
|
||||
return isArrayTy() || isVectorTy() ? getTypeArray().getNumElements() : 1;
|
||||
}
|
||||
|
||||
inline void EDIType::setCurrentDimension(unsigned dimension) {
|
||||
assert(dimension < getNumDimensions());
|
||||
this->currentDimension = dimension;
|
||||
}
|
||||
|
||||
inline unsigned EDIType::getCurrentDimension() const {
|
||||
return currentDimension;
|
||||
}
|
||||
|
||||
inline const DIType *EDIType::getDIType() const {
|
||||
return &aDIType;
|
||||
}
|
||||
|
||||
inline StringRef EDIType::getName() const {
|
||||
return myName;
|
||||
}
|
||||
|
||||
inline std::vector<StringRef> EDIType::getNames() const {
|
||||
return myNames;
|
||||
}
|
||||
|
||||
inline StringRef EDIType::getNamesString() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
for(unsigned i=0;i<myNames.size();i++) {
|
||||
if(i>0) ostream << "|";
|
||||
ostream << myNames[i];
|
||||
}
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
inline std::vector<unsigned> EDIType::getEnumValues() const {
|
||||
assert(isEnumTy());
|
||||
std::vector<unsigned> enumValues;
|
||||
DIArray aDIArray = getTypeArray();
|
||||
unsigned numValues = aDIArray.getNumElements();
|
||||
for(unsigned i=0;i<numValues;i++) {
|
||||
DIDescriptor aDIDescriptor = aDIArray.getElement(i);
|
||||
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_enumerator);
|
||||
const unsigned value = (unsigned) ((DIEnumerator)aDIDescriptor).getEnumValue();
|
||||
enumValues.push_back(value);
|
||||
}
|
||||
return enumValues;
|
||||
}
|
||||
|
||||
inline unsigned EDIType::getTag()const {
|
||||
return aDIType.getTag();
|
||||
}
|
||||
|
||||
inline EDIType EDIType::getTypeDerivedFrom() const {
|
||||
EDIType_assert(isDerivedType() || isCompositeType());
|
||||
EDIType subType(PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType));
|
||||
return subType;
|
||||
}
|
||||
|
||||
inline bool EDIType::isType() const {
|
||||
return aDIType.isType() || isVoidTy();
|
||||
}
|
||||
|
||||
inline bool EDIType::isBasicType() const {
|
||||
return aDIType.isBasicType();
|
||||
}
|
||||
|
||||
inline bool EDIType::isDerivedType() const {
|
||||
return aDIType.isDerivedType() && !aDIType.isCompositeType();
|
||||
}
|
||||
|
||||
inline bool EDIType::isCompositeType() const {
|
||||
return aDIType.isCompositeType();
|
||||
}
|
||||
|
||||
inline bool EDIType::isPrimitiveType() const {
|
||||
return (isVoidTy() || isFloatingPointTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isAggregateType() const {
|
||||
return isUnionOrStructTy() || isArrayTy() || isVectorTy();
|
||||
}
|
||||
|
||||
inline bool EDIType::isVoidTy() const {
|
||||
return !aDIType.isValid(); //xxx we should keep track of this to spot all the i8* = void*
|
||||
}
|
||||
|
||||
inline bool EDIType::isComplexFloatingPointTy() const {
|
||||
if(!isBasicType()) return false;
|
||||
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_complex_float);
|
||||
}
|
||||
|
||||
inline bool EDIType::isFloatingPointTy() const {
|
||||
if(!isBasicType()) return false;
|
||||
return EDIType::isComplexFloatingPointTy() || (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_float);
|
||||
}
|
||||
|
||||
inline bool EDIType::isCharTy() const {
|
||||
if(!isBasicType()) return false;
|
||||
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed_char ||
|
||||
((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned_char);
|
||||
}
|
||||
|
||||
inline bool EDIType::isIntTy() const {
|
||||
if(!isBasicType()) return false;
|
||||
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed ||
|
||||
((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned);
|
||||
}
|
||||
|
||||
inline bool EDIType::isBoolTy() const {
|
||||
if(!isBasicType()) return false;
|
||||
return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_boolean);
|
||||
}
|
||||
|
||||
inline bool EDIType::isIntegerTy() const {
|
||||
return (isCharTy() || isIntTy() || isBoolTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isFunctionTy() const {
|
||||
return (getTag() == dwarf::DW_TAG_subroutine_type && !isOpaqueTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isArrayTy() const {
|
||||
return (getTag() == dwarf::DW_TAG_array_type && !isOpaqueTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isEnumTy() const {
|
||||
return (getTag() == dwarf::DW_TAG_enumeration_type && !isOpaqueTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isVectorTy() const {
|
||||
return (PassUtil::isDbgVectorTy(aDIType) && !isOpaqueTy());
|
||||
}
|
||||
|
||||
inline bool EDIType::isUnionTy() const {
|
||||
return isUnionOrStructTy(false, true);
|
||||
}
|
||||
|
||||
inline bool EDIType::isStructTy() const {
|
||||
return isUnionOrStructTy(true, false);
|
||||
}
|
||||
|
||||
inline bool EDIType::isPointerTy() const {
|
||||
return (getTag() == dwarf::DW_TAG_pointer_type);
|
||||
}
|
||||
|
||||
inline bool EDIType::isOpaqueTy() const {
|
||||
return (isCompositeType() && getTypeArray().getNumElements() == 0);
|
||||
}
|
||||
|
||||
inline void EDIType::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
|
||||
return PassUtil::writeTypeSymbolic(OS, type, M);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
230
minix/llvm/passes/include/magic/support/MagicDebugFunction.h
Normal file
230
minix/llvm/passes/include/magic/support/MagicDebugFunction.h
Normal file
|
@ -0,0 +1,230 @@
|
|||
#ifndef MAGIC_DEBUG_FUNCTION_H_
|
||||
#define MAGIC_DEBUG_FUNCTION_H_
|
||||
|
||||
#include <pass.h>
|
||||
|
||||
#define NUM_DEBUG_ARGS 1
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MagicDebugFunction {
|
||||
public:
|
||||
MagicDebugFunction(Function *function);
|
||||
|
||||
Function* getFunction() const;
|
||||
void addHooks(std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
|
||||
void fixCalls(Module &M, const std::string &baseDir="");
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void printDescription(raw_ostream &OS) const;
|
||||
const std::string getDescription() const;
|
||||
static bool inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping,
|
||||
std::vector<Value*> trailingArgs);
|
||||
Function* getDebugFunction(Module &M);
|
||||
|
||||
private:
|
||||
Function *function;
|
||||
|
||||
std::pair<Function*, Function*> hooks;
|
||||
unsigned flags;
|
||||
std::vector<unsigned> argsMapping;
|
||||
std::vector<Value*> trailingArgs;
|
||||
|
||||
Function* getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType);
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MagicDebugFunction &aMagicDebugFunction) {
|
||||
aMagicDebugFunction.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline void MagicDebugFunction::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
inline void MagicDebugFunction::printDescription(raw_ostream &OS) const {
|
||||
OS << "[ function = ";
|
||||
OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ") ]";
|
||||
}
|
||||
|
||||
inline const std::string MagicDebugFunction::getDescription() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
printDescription(ostream);
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
inline Function* MagicDebugFunction::getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType) {
|
||||
Function* wrapper;
|
||||
std::vector<TYPECONST Type*> ArgTypes;
|
||||
VALUE_TO_VALUE_MAP_TY VMap;
|
||||
|
||||
// Build arg types for wrapper
|
||||
ArgTypes.push_back(debugArgType);
|
||||
Function::const_arg_iterator E = function->arg_end();
|
||||
for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
|
||||
ArgTypes.push_back(I->getType());
|
||||
|
||||
// Create a new function type...
|
||||
FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
|
||||
|
||||
// Create the wrapper
|
||||
wrapper = Function::Create(FTy, function->getLinkage(), wrapperName, function->getParent());
|
||||
|
||||
// Loop over the arguments, copying the names of the mapped arguments over...
|
||||
Function::arg_iterator DestI = wrapper->arg_begin();
|
||||
Value *magicTypeValue = DestI;
|
||||
magicTypeValue->setName("cs_info");
|
||||
DestI++;
|
||||
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
|
||||
DestI->setName(I->getName());
|
||||
VMap[I] = DestI++;
|
||||
}
|
||||
|
||||
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
|
||||
CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
inline MagicDebugFunction::MagicDebugFunction(Function *function) {
|
||||
this->function = function;
|
||||
}
|
||||
|
||||
inline void MagicDebugFunction::addHooks(std::pair<Function*, Function*> aHooks, unsigned aFlags, std::vector<unsigned> aArgsMapping,
|
||||
std::vector<Value*> aTrailingArgs) {
|
||||
hooks = aHooks;
|
||||
flags = aFlags;
|
||||
trailingArgs = aTrailingArgs;
|
||||
argsMapping = aArgsMapping;
|
||||
}
|
||||
|
||||
inline Function* MagicDebugFunction::getFunction() const {
|
||||
return function;
|
||||
}
|
||||
|
||||
inline Function* MagicDebugFunction::getDebugFunction(Module &M) {
|
||||
PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
|
||||
Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
|
||||
bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
|
||||
if (ret) {
|
||||
return debugFunction;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline void MagicDebugFunction::fixCalls(Module &M, const std::string &baseDir) {
|
||||
PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
|
||||
Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
|
||||
bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
|
||||
assert(ret && "Unable to inline the calls to the hook functions.");
|
||||
|
||||
std::vector<User*> Users(function->use_begin(), function->use_end());
|
||||
std::vector<Value*> EqPointers;
|
||||
while (!Users.empty()) {
|
||||
User *U = Users.back();
|
||||
Users.pop_back();
|
||||
|
||||
if (Instruction * I = dyn_cast<Instruction>(U)) {
|
||||
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
|
||||
if (CS.getInstruction()
|
||||
&& (MagicUtil::getCalledFunctionFromCS(CS) == function
|
||||
|| std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) {
|
||||
Function *parentFunction = CS.getInstruction()->getParent()->getParent();
|
||||
StringRef callParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseDir);
|
||||
//extend function name with debug information
|
||||
if (MDNode *N = I->getMetadata("dbg")) {
|
||||
DILocation Loc(N);
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
ostream << callParentName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
|
||||
ostream.flush();
|
||||
callParentName = string;
|
||||
}
|
||||
Value* callParentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, callParentName));
|
||||
std::vector<Value*> debugArgs;
|
||||
debugArgs.push_back(callParentNameValue);
|
||||
debugArgs.insert(debugArgs.end(), CS.arg_begin(), CS.arg_end());
|
||||
CallInst* newInst = MagicUtil::createCallInstruction(debugFunction, debugArgs, "", I);
|
||||
newInst->takeName(I);
|
||||
MagicUtil::replaceCallInst(I, newInst, 1);
|
||||
}
|
||||
} else if (GlobalValue * GV = dyn_cast<GlobalValue>(U)) {
|
||||
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
|
||||
EqPointers.push_back(GV);
|
||||
} else if (ConstantExpr * CE = dyn_cast<ConstantExpr>(U)) {
|
||||
if (CE->isCast()) {
|
||||
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
|
||||
EqPointers.push_back(CE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// inlines calls to the pre and post hooks and returns true if the inlining succeeded, false otherwise
|
||||
inline bool MagicDebugFunction::inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags,
|
||||
std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs) {
|
||||
std::vector<Value*> emptyArgs;
|
||||
std::vector<unsigned> emptyMapping;
|
||||
std::vector<unsigned> debugEmptyMapping;
|
||||
std::vector<unsigned> debugArgsMapping;
|
||||
|
||||
// debug version of the function, argument mapping has to be adjusted
|
||||
if (flags & MAGIC_HOOK_DEBUG_MASK) {
|
||||
// re-adjusted the index of the arguments (do not re-adjust return value)
|
||||
for (unsigned i = 0; i < argsMapping.size(); i++) {
|
||||
if (argsMapping[i] > 0) {
|
||||
argsMapping[i] += NUM_DEBUG_ARGS;
|
||||
}
|
||||
}
|
||||
// first come the debug argument
|
||||
for (unsigned i = 1; i <= NUM_DEBUG_ARGS; i++) {
|
||||
debugEmptyMapping.push_back(i);
|
||||
debugArgsMapping.push_back(i);
|
||||
}
|
||||
debugArgsMapping.insert(debugArgsMapping.end(), argsMapping.begin(), argsMapping.end());
|
||||
}
|
||||
|
||||
if (hooks.first != NULL) {
|
||||
// inline first hook call at the beginning of the function, according to the flag
|
||||
switch (flags & MAGIC_PRE_HOOK_FLAGS_MASK) {
|
||||
case MAGIC_PRE_HOOK_SIMPLE_CALL:
|
||||
MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
|
||||
emptyArgs);
|
||||
break;
|
||||
case MAGIC_PRE_HOOK_FORWARDING_CALL:
|
||||
MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
|
||||
trailingArgs);
|
||||
break;
|
||||
default:
|
||||
// unknown flag
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hooks.second != NULL) {
|
||||
// inline the second wrapper call at the end of the function, according to the flag
|
||||
switch (flags & MAGIC_POST_HOOK_FLAGS_MASK) {
|
||||
case MAGIC_POST_HOOK_SIMPLE_CALL:
|
||||
MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
|
||||
emptyArgs);
|
||||
break;
|
||||
case MAGIC_POST_HOOK_FORWARDING_CALL:
|
||||
MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
|
||||
trailingArgs);
|
||||
break;
|
||||
default:
|
||||
// unknown flag
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* MAGIC_DEBUG_FUNCTION_H_ */
|
547
minix/llvm/passes/include/magic/support/MagicMemFunction.h
Normal file
547
minix/llvm/passes/include/magic/support/MagicMemFunction.h
Normal file
|
@ -0,0 +1,547 @@
|
|||
#ifndef MAGIC_MEM_FUNCTION_H
|
||||
#define MAGIC_MEM_FUNCTION_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic/support/TypeInfo.h>
|
||||
|
||||
#define NUM_MAGIC_ARGS 3
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MagicMemFunction {
|
||||
public:
|
||||
MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags);
|
||||
|
||||
Function* getFunction() const;
|
||||
Function* getWrapper() const;
|
||||
bool isDeallocFunction() const;
|
||||
int getAllocFlags() const;
|
||||
Instruction* getInstruction() const;
|
||||
Function* getInstructionParent() const;
|
||||
TypeInfo* getInstructionTypeInfo() const;
|
||||
Value* getInstructionTypeValue() const;
|
||||
bool hasInstructionType() const;
|
||||
std::vector<MagicMemFunction> getInstructionDeps() const;
|
||||
|
||||
void setInstruction(Instruction* I);
|
||||
void setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName);
|
||||
void setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue);
|
||||
void addInstructionDep(MagicMemFunction &function);
|
||||
void replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void printDescription(raw_ostream &OS) const;
|
||||
const std::string getDescription() const;
|
||||
|
||||
static int getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo);
|
||||
static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
|
||||
bool isDealloc);
|
||||
static bool isCustomWrapper(Function *function);
|
||||
|
||||
private:
|
||||
Module *module;
|
||||
Function *function;
|
||||
Function *wrapper;
|
||||
bool isDealloc;
|
||||
int allocFlags;
|
||||
Instruction *instruction;
|
||||
TypeInfo* aTypeInfo;
|
||||
std::string allocName;
|
||||
std::string allocParentName;
|
||||
Value* typeValue;
|
||||
Value* allocNameValue;
|
||||
Value* allocParentNameValue;
|
||||
std::vector<MagicMemFunction> instructionDeps;
|
||||
|
||||
void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
|
||||
|
||||
static Function *lastAllocWrapper;
|
||||
static std::map<std::string, Function*> allocWrapperCache;
|
||||
static std::set<Function*> customWrapperSet;
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
|
||||
aMagicMemFunction.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::printDescription(raw_ostream &OS) const {
|
||||
OS << "[ function = ";
|
||||
OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")";
|
||||
OS << ", wrapper = ";
|
||||
if (wrapper) {
|
||||
OS << wrapper->getName() << "(" << TypeUtil::getDescription(wrapper->getFunctionType()) << ")";
|
||||
} else
|
||||
OS << "NULL";
|
||||
OS << ", isDeallocFunction = ";
|
||||
OS << isDealloc;
|
||||
OS << ", instruction = ";
|
||||
if (instruction)
|
||||
instruction->print(OS);
|
||||
else
|
||||
OS << "NULL";
|
||||
OS << ", typeInfo = ";
|
||||
if (aTypeInfo)
|
||||
OS << aTypeInfo->getDescription();
|
||||
else
|
||||
OS << "NULL";
|
||||
OS << ", allocName = ";
|
||||
OS << allocName;
|
||||
OS << ", allocParentName = ";
|
||||
OS << allocParentName;
|
||||
OS << ", typeValue = ";
|
||||
if (typeValue)
|
||||
typeValue->print(OS);
|
||||
else
|
||||
OS << "NULL";
|
||||
OS << ", allocNameValue = ";
|
||||
if (allocNameValue)
|
||||
allocNameValue->print(OS);
|
||||
else
|
||||
OS << "NULL";
|
||||
OS << ", allocParentNameValue = ";
|
||||
if (allocParentNameValue)
|
||||
allocParentNameValue->print(OS);
|
||||
else
|
||||
OS << "NULL";
|
||||
OS << ", instructionDeps = {";
|
||||
for (unsigned i = 0; i < instructionDeps.size(); i++) {
|
||||
if (i > 0) {
|
||||
OS << ", ";
|
||||
}
|
||||
instructionDeps[i].print(OS);
|
||||
}
|
||||
OS << "}]";
|
||||
}
|
||||
|
||||
inline const std::string MagicMemFunction::getDescription() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
printDescription(ostream);
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
inline MagicMemFunction::MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, int allocFlags) {
|
||||
this->module = &M;
|
||||
this->function = function;
|
||||
this->wrapper = wrapper;
|
||||
this->isDealloc = isDealloc;
|
||||
this->allocFlags = allocFlags;
|
||||
this->instruction = NULL;
|
||||
this->aTypeInfo = NULL;
|
||||
this->allocName = "";
|
||||
this->allocParentName = "";
|
||||
this->typeValue = NULL;
|
||||
this->allocNameValue = NULL;
|
||||
this->allocParentNameValue = NULL;
|
||||
assert(function);
|
||||
if (wrapper && !isDealloc) {
|
||||
lastAllocWrapper = wrapper;
|
||||
}
|
||||
if (isDealloc) {
|
||||
assert(!allocFlags);
|
||||
}
|
||||
}
|
||||
|
||||
inline Function* MagicMemFunction::getFunction() const {
|
||||
return function;
|
||||
}
|
||||
|
||||
inline Function* MagicMemFunction::getWrapper() const {
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
inline bool MagicMemFunction::isDeallocFunction() const {
|
||||
return isDealloc;
|
||||
}
|
||||
|
||||
inline int MagicMemFunction::getAllocFlags() const {
|
||||
return allocFlags;
|
||||
}
|
||||
|
||||
inline Instruction* MagicMemFunction::getInstruction() const {
|
||||
return instruction;
|
||||
}
|
||||
|
||||
inline Function* MagicMemFunction::getInstructionParent() const {
|
||||
if (!instruction) {
|
||||
return NULL;
|
||||
}
|
||||
return instruction->getParent()->getParent();
|
||||
}
|
||||
|
||||
inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
|
||||
return aTypeInfo;
|
||||
}
|
||||
|
||||
inline Value* MagicMemFunction::getInstructionTypeValue() const {
|
||||
return typeValue;
|
||||
}
|
||||
|
||||
inline bool MagicMemFunction::hasInstructionType() const {
|
||||
return aTypeInfo || typeValue;
|
||||
}
|
||||
|
||||
inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
|
||||
return instructionDeps;
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::setInstruction(Instruction* I) {
|
||||
this->instruction = I;
|
||||
assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName) {
|
||||
this->aTypeInfo = aTypeInfo;
|
||||
this->allocName = allocName;
|
||||
this->allocParentName = allocParentName;
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
|
||||
this->typeValue = typeValue;
|
||||
this->allocNameValue = allocNameValue;
|
||||
this->allocParentNameValue = allocParentNameValue;
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::addInstructionDep(MagicMemFunction &function) {
|
||||
assert(wrapper == NULL && "Dependencies are resolved at wrapper building time, so wrapper has to be NULL!");
|
||||
instructionDeps.push_back(function);
|
||||
allocFlags |= function.getAllocFlags();
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
|
||||
Instruction *I = getInstruction();
|
||||
assert(I);
|
||||
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
|
||||
std::vector<Value*> magicMemArgs;
|
||||
unsigned numMagicArgs = 0;
|
||||
//if we do not have a wrapper, build one
|
||||
if (!wrapper) {
|
||||
buildWrapper(magicArrayTypePtrMap, voidPtrTypeInfo);
|
||||
}
|
||||
//inject magic args
|
||||
if (!isDeallocFunction()) {
|
||||
std::map<TypeInfo*, Constant*>::iterator it;
|
||||
if (!typeValue) {
|
||||
assert(aTypeInfo);
|
||||
if (aTypeInfo == voidPtrTypeInfo->getContainedType(0)) {
|
||||
typeValue = ConstantPointerNull::get((TYPECONST PointerType*) (wrapper->arg_begin()->getType()));
|
||||
} else {
|
||||
it = magicArrayTypePtrMap.find(aTypeInfo);
|
||||
assert(it != magicArrayTypePtrMap.end());
|
||||
typeValue = it->second;
|
||||
}
|
||||
assert(allocName.compare(""));
|
||||
assert(allocParentName.compare(""));
|
||||
allocNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocName));
|
||||
allocParentNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocParentName));
|
||||
}
|
||||
magicMemArgs.push_back(typeValue);
|
||||
magicMemArgs.push_back(allocNameValue);
|
||||
magicMemArgs.push_back(allocParentNameValue);
|
||||
numMagicArgs = NUM_MAGIC_ARGS;
|
||||
}
|
||||
//push other args
|
||||
unsigned arg_size = MagicUtil::getCalledFunctionFromCS(CS)->getFunctionType()->getNumContainedTypes() - 1;
|
||||
for (unsigned i = 0; i < arg_size; i++) {
|
||||
Value *arg = CS.getArgument(i);
|
||||
TYPECONST Type* wArgType = wrapper->getFunctionType()->getContainedType(i + numMagicArgs + 1);
|
||||
if (arg->getType() != wArgType) {
|
||||
if (arg->getType()->isPointerTy()) {
|
||||
assert(wArgType->isPointerTy());
|
||||
arg = CastInst::CreatePointerCast(arg, wArgType, "WrapperCast", I);
|
||||
}
|
||||
else {
|
||||
assert(arg->getType()->isIntegerTy());
|
||||
assert(wArgType->isIntegerTy());
|
||||
arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
|
||||
}
|
||||
}
|
||||
magicMemArgs.push_back(arg);
|
||||
}
|
||||
//replace function with wrapper
|
||||
CallInst* newInst = MagicUtil::createCallInstruction(wrapper, magicMemArgs, "", I);
|
||||
newInst->takeName(I);
|
||||
MagicUtil::replaceCallInst(I, newInst, NUM_MAGIC_ARGS);
|
||||
}
|
||||
|
||||
inline int MagicMemFunction::getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo) {
|
||||
TYPECONST Type *type = function->getReturnType();
|
||||
if (type == voidPtrTypeInfo->getType()) {
|
||||
return 0;
|
||||
} else if (brkFunctions.find(function) != brkFunctions.end()) {
|
||||
return 1;
|
||||
} else {
|
||||
unsigned i;
|
||||
for (i = 1; i < function->getFunctionType()->getNumContainedTypes(); i++) {
|
||||
type = function->getFunctionType()->getContainedType(i);
|
||||
if (type->isPointerTy() && type->getContainedType(0) == voidPtrTypeInfo->getType()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void MagicMemFunction::buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
|
||||
assert(!isDeallocFunction());
|
||||
assert(lastAllocWrapper);
|
||||
std::vector<TYPECONST Type*> ArgTypes;
|
||||
VALUE_TO_VALUE_MAP_TY VMap;
|
||||
|
||||
std::map<std::string, Function*>::iterator allocWrapperCacheIt;
|
||||
|
||||
// See if the wrapper is in cache, otherwise create a new wrapper using function cloning
|
||||
allocWrapperCacheIt = allocWrapperCache.find(function->getName());
|
||||
if (allocWrapperCacheIt != allocWrapperCache.end()) {
|
||||
wrapper = allocWrapperCacheIt->second;
|
||||
return;
|
||||
}
|
||||
|
||||
// Build arg types for wrapper
|
||||
Function::const_arg_iterator E = lastAllocWrapper->arg_begin();
|
||||
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
|
||||
E++;
|
||||
for (Function::const_arg_iterator I = lastAllocWrapper->arg_begin(); I != E; ++I)
|
||||
ArgTypes.push_back(I->getType());
|
||||
E = function->arg_end();
|
||||
for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
|
||||
ArgTypes.push_back(I->getType());
|
||||
|
||||
// Create a new function type...
|
||||
FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
|
||||
|
||||
// Create the wrapper
|
||||
wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
|
||||
|
||||
// Loop over the arguments, copying the names of the mapped arguments over...
|
||||
Function::arg_iterator DestI = wrapper->arg_begin();
|
||||
Value *magicTypeValue = DestI;
|
||||
magicTypeValue->setName("magic_type");
|
||||
DestI++;
|
||||
Value *magicNameValue = DestI;
|
||||
magicNameValue->setName("magic_name");
|
||||
DestI++;
|
||||
Value *magicParentNameValue = DestI;
|
||||
magicParentNameValue->setName("magic_parent_name");
|
||||
DestI++;
|
||||
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
|
||||
DestI->setName(I->getName());
|
||||
VMap[I] = DestI++;
|
||||
}
|
||||
|
||||
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
|
||||
CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
|
||||
|
||||
allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
|
||||
|
||||
// Create a mapping between the function instruction pointers and the wrapper instruction pointers
|
||||
std::vector<Instruction *> wrapperInstructionDeps;
|
||||
for (unsigned i = 0; i < instructionDeps.size(); i++) {
|
||||
Instruction *instruction = instructionDeps[i].getInstruction();
|
||||
Instruction *wrapperInstruction = NULL;
|
||||
unsigned instructionOffset = 0;
|
||||
for (inst_iterator I = inst_begin(function), E = inst_end(function); I != E; ++I, instructionOffset++) {
|
||||
if (instruction == &(*I)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(instructionOffset > 0);
|
||||
for (inst_iterator I = inst_begin(wrapper), E = inst_end(wrapper); I != E; ++I, instructionOffset--) {
|
||||
if (instructionOffset == 0) {
|
||||
wrapperInstruction = &(*I);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(wrapperInstruction);
|
||||
wrapperInstructionDeps.push_back(wrapperInstruction);
|
||||
}
|
||||
|
||||
// Forward magic type argument to any dependent instruction and replace it
|
||||
for (unsigned i = 0; i < wrapperInstructionDeps.size(); i++) {
|
||||
instructionDeps[i].setInstruction(wrapperInstructionDeps[i]);
|
||||
instructionDeps[i].setInstructionTypeValue(magicTypeValue, magicNameValue, magicParentNameValue);
|
||||
instructionDeps[i].replaceInstruction(magicArrayTypePtrMap, voidPtrTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
inline Function* MagicMemFunction::getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
|
||||
bool isDealloc) {
|
||||
Function* wrapper;
|
||||
std::vector<TYPECONST Type*> ArgTypes;
|
||||
VALUE_TO_VALUE_MAP_TY VMap;
|
||||
|
||||
// Build arg types for wrapper
|
||||
// add magic arguments
|
||||
if (!isDealloc) {
|
||||
Function::const_arg_iterator E = stdWrapper->arg_begin();
|
||||
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
|
||||
E++;
|
||||
for (Function::const_arg_iterator I = stdWrapper->arg_begin(); I != E; ++I) {
|
||||
ArgTypes.push_back(I->getType());
|
||||
}
|
||||
}
|
||||
// add original function arguments
|
||||
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
|
||||
ArgTypes.push_back(I->getType());
|
||||
}
|
||||
|
||||
// Create a new function type...
|
||||
FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
|
||||
|
||||
// Create the wrapper
|
||||
wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
|
||||
|
||||
// Loop over the arguments, copying the names of the mapped arguments over...
|
||||
Function::arg_iterator DestI = wrapper->arg_begin();
|
||||
std::vector<Value*> wrapperArgs;
|
||||
if (!isDealloc) {
|
||||
std::string magicArgs[] = { "magic_type", "magic_name", "magic_parent_name" };
|
||||
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
|
||||
DestI->setName(magicArgs[i]);
|
||||
wrapperArgs.push_back(DestI);
|
||||
DestI++;
|
||||
}
|
||||
}
|
||||
for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
|
||||
DestI->setName(I->getName());
|
||||
wrapperArgs.push_back(DestI);
|
||||
DestI++;
|
||||
}
|
||||
|
||||
// map the arguments of the standard wrapper to the arguments of the new custom wrapper
|
||||
if ((!isDealloc) || argMapping.size()) {
|
||||
Function::const_arg_iterator W = stdWrapper->arg_begin();
|
||||
if (!isDealloc) {
|
||||
// magic arguments are in the same position
|
||||
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
|
||||
VMap[W] = wrapperArgs[i];
|
||||
W++;
|
||||
}
|
||||
}
|
||||
// map the selected arguments of the custom wrapper using the mapping provided as input
|
||||
unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
|
||||
for (unsigned i = 0; i < argMapping.size(); i++) {
|
||||
VMap[W] = wrapperArgs[argOffset + argMapping[i] - 1];
|
||||
W++;
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
|
||||
CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
|
||||
|
||||
// check whether some of the arguments of the custom wrapper need to be casted
|
||||
// in order to match the basic wrapper implementation
|
||||
Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(wrapper);
|
||||
Function::const_arg_iterator W = stdWrapper->arg_begin();
|
||||
unsigned argOffset = 0;
|
||||
if (!isDealloc) {
|
||||
argOffset = NUM_MAGIC_ARGS;
|
||||
// skip the magic arguments, they are always the same
|
||||
for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
|
||||
W++;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < argMapping.size(); i++) {
|
||||
TYPECONST Type* StdParamType = W->getType();
|
||||
Value* ParamValue = wrapperArgs[argOffset + argMapping[i] - 1];
|
||||
TYPECONST Type* ParamType = ParamValue->getType();
|
||||
if (!MagicUtil::isCompatibleType(ParamType, StdParamType)) {
|
||||
assert(CastInst::isCastable(ParamType, StdParamType) && "The type of the parameter of the custom wrapper "
|
||||
"cannot be casted to the type of the basic wrapper to which it is corresponding.");
|
||||
Instruction::CastOps CastOpCode = CastInst::getCastOpcode(ParamValue, false, StdParamType, false);
|
||||
Instruction *ParamCastInst = CastInst::Create(CastOpCode, ParamValue, StdParamType, "", FirstInst);
|
||||
|
||||
for (Value::use_iterator it = ParamValue->use_begin(); it != ParamValue->use_end(); it++) {
|
||||
if (Constant * C = dyn_cast<Constant>(*it)) {
|
||||
if (!isa<GlobalValue>(C)) {
|
||||
C->replaceUsesOfWith(ParamValue, ParamCastInst);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Instruction *I = dyn_cast<Instruction>(*it);
|
||||
if (I && (I != ParamCastInst)) {
|
||||
// replace all uses, except for the calls to the wrapped function
|
||||
CallInst *CI = dyn_cast<CallInst>(I);
|
||||
if (CI && (CI->getCalledFunction() == function)) {
|
||||
continue;
|
||||
}
|
||||
I->replaceUsesOfWith(ParamValue, ParamCastInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
W++;
|
||||
}
|
||||
|
||||
// replace the call(s) to the standard function with calls to our function
|
||||
for (Function::iterator BI = wrapper->getBasicBlockList().begin(), BE = wrapper->getBasicBlockList().end(); BI != BE; ++BI) {
|
||||
unsigned pos = 0;
|
||||
unsigned bbSize = BI->getInstList().size();
|
||||
while (pos < bbSize) {
|
||||
BasicBlock::iterator it = BI->getInstList().begin();
|
||||
for (unsigned i = 0; i < pos; i++) {
|
||||
it++;
|
||||
}
|
||||
Instruction *inst = &(*it);
|
||||
// find the calls to the standard function
|
||||
CallInst *callInst = dyn_cast<CallInst>(inst);
|
||||
if (callInst && callInst->getCalledFunction() && (callInst->getCalledFunction()->getFunctionType() == stdFunction->getFunctionType())
|
||||
&& (!callInst->getCalledFunction()->getName().compare(stdFunction->getName()))) {
|
||||
CallSite CS = MagicUtil::getCallSiteFromInstruction(callInst);
|
||||
unsigned numStdParams = stdFunction->getFunctionType()->getNumParams();
|
||||
unsigned numParams = function->getFunctionType()->getNumParams();
|
||||
// construct the parameter array
|
||||
std::vector<Value*> callArgs(numParams, NULL);
|
||||
// first add the arguments that are common to the custom and standard function
|
||||
// add casts where necessary
|
||||
for (unsigned i = 0; i < numStdParams; i++) {
|
||||
Value *argValue = CS.getArgument(i);
|
||||
TYPECONST Type* paramType = function->getFunctionType()->getParamType(i);
|
||||
TYPECONST Type* argType = argValue->getType();
|
||||
if (paramType != argType) {
|
||||
assert(CastInst::isCastable(argType, paramType) && "The value of the argument cannot be "
|
||||
"casted to the parameter type required by the function to be called.");
|
||||
Instruction::CastOps opcode = CastInst::getCastOpcode(argValue, false, paramType, false);
|
||||
argValue = CastInst::Create(opcode, argValue, paramType, "", callInst);
|
||||
}
|
||||
callArgs[argMapping[i] - 1] = argValue;
|
||||
}
|
||||
// the other arguments are just forwarded from the wrapper's argument list
|
||||
// skip the magic arguments of the wrapper from the beginning of the argument list
|
||||
unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
|
||||
for (unsigned i = argOffset; i < wrapper->getFunctionType()->getNumParams(); i++) {
|
||||
if (callArgs[i - argOffset] == NULL) {
|
||||
Value* arg = wrapperArgs[i];
|
||||
callArgs[i - argOffset] = arg;
|
||||
}
|
||||
}
|
||||
|
||||
CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
|
||||
newCallInst->takeName(callInst);
|
||||
MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
customWrapperSet.insert(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
inline bool MagicMemFunction::isCustomWrapper(Function *function)
|
||||
{
|
||||
return customWrapperSet.find(function) != customWrapperSet.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
130
minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h
Normal file
130
minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
#ifndef MAGIC_MMAP_CTL_FUNCTION_H
|
||||
#define MAGIC_MMAP_CTL_FUNCTION_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic/support/TypeInfo.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MagicMmapCtlFunction {
|
||||
public:
|
||||
MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName);
|
||||
|
||||
Function* getFunction() const;
|
||||
void fixCalls(Module &M, Function *magicGetPageSizeFunc) const;
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void printDescription(raw_ostream &OS) const;
|
||||
const std::string getDescription() const;
|
||||
|
||||
private:
|
||||
Function *function;
|
||||
int ptrArg;
|
||||
int lenArg;
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MagicMmapCtlFunction &aMagicMmapCtlFunction) {
|
||||
aMagicMmapCtlFunction.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline void MagicMmapCtlFunction::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
inline void MagicMmapCtlFunction::printDescription(raw_ostream &OS) const {
|
||||
OS << "[ function = "; OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")"
|
||||
<< ", ptr arg = "; OS << ptrArg
|
||||
<< ", len arg = "; OS << lenArg
|
||||
<< "]";
|
||||
}
|
||||
|
||||
inline const std::string MagicMmapCtlFunction::getDescription() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
printDescription(ostream);
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
inline MagicMmapCtlFunction::MagicMmapCtlFunction(Function *function, PointerType *voidPointerType, std::string &ptrArgName, std::string &lenArgName) {
|
||||
this->function = function;
|
||||
this->ptrArg = -1;
|
||||
this->lenArg = -1;
|
||||
bool lookupPtrArg = ptrArgName.compare("");
|
||||
bool lookupLenArg = lenArgName.compare("");
|
||||
assert((lookupPtrArg || lookupLenArg) && "No valid argument name specified!");
|
||||
unsigned i=0;
|
||||
for (Function::arg_iterator it = function->arg_begin(), E = function->arg_end();
|
||||
it != E; ++it) {
|
||||
std::string argName = it->getName();
|
||||
if(lookupPtrArg && !argName.compare(ptrArgName)) {
|
||||
this->ptrArg = i;
|
||||
}
|
||||
else if(lookupLenArg && !argName.compare(lenArgName)) {
|
||||
this->lenArg = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(this->ptrArg >= 0) {
|
||||
assert(function->getFunctionType()->getContainedType(this->ptrArg+1) == voidPointerType && "Invalid ptr argument specified!");
|
||||
}
|
||||
else {
|
||||
assert(!lookupPtrArg && "Invalid ptr argument name specified!");
|
||||
}
|
||||
if(this->lenArg >= 0) {
|
||||
assert(isa<IntegerType>(function->getFunctionType()->getContainedType(this->lenArg+1)) && "Invalid len argument specified!");
|
||||
}
|
||||
else {
|
||||
assert(!lookupLenArg && "Invalid len argument name specified!");
|
||||
}
|
||||
}
|
||||
|
||||
inline Function* MagicMmapCtlFunction::getFunction() const {
|
||||
return function;
|
||||
}
|
||||
|
||||
/* This assumes in-band metadata of 1 page before every mmapped region. */
|
||||
inline void MagicMmapCtlFunction::fixCalls(Module &M, Function *magicGetPageSizeFunc) const {
|
||||
std::vector<User*> Users(function->use_begin(), function->use_end());
|
||||
while (!Users.empty()) {
|
||||
User *U = Users.back();
|
||||
Users.pop_back();
|
||||
|
||||
if (Instruction *I = dyn_cast<Instruction>(U)) {
|
||||
Function *parent = I->getParent()->getParent();
|
||||
if(parent->getName().startswith("magic") || parent->getName().startswith("_magic")) {
|
||||
continue;
|
||||
}
|
||||
CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
|
||||
|
||||
std::vector<Value*> args;
|
||||
CallInst* magicGetPageSizeCall = MagicUtil::createCallInstruction(magicGetPageSizeFunc, args, "", I);
|
||||
magicGetPageSizeCall->setCallingConv(CallingConv::C);
|
||||
magicGetPageSizeCall->setTailCall(false);
|
||||
TYPECONST IntegerType *type = dyn_cast<IntegerType>(magicGetPageSizeCall->getType());
|
||||
assert(type);
|
||||
|
||||
if(this->ptrArg >= 0) {
|
||||
Value *ptrValue = CS.getArgument(this->ptrArg);
|
||||
BinaryOperator* negativePageSize = BinaryOperator::Create(Instruction::Sub, ConstantInt::get(M.getContext(), APInt(type->getBitWidth(), 0)), magicGetPageSizeCall, "", I);
|
||||
GetElementPtrInst* ptrValueWithOffset = GetElementPtrInst::Create(ptrValue, negativePageSize, "", I);
|
||||
|
||||
CS.setArgument(this->ptrArg, ptrValueWithOffset);
|
||||
}
|
||||
if(this->lenArg >= 0) {
|
||||
Value *lenValue = CS.getArgument(this->lenArg);
|
||||
BinaryOperator* lenValuePlusPageSize = BinaryOperator::Create(Instruction::Add, lenValue, magicGetPageSizeCall, "", I);
|
||||
|
||||
CS.setArgument(this->lenArg, lenValuePlusPageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
72
minix/llvm/passes/include/magic/support/MagicUtil.h
Normal file
72
minix/llvm/passes/include/magic/support/MagicUtil.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef MAGIC_UTIL_H
|
||||
#define MAGIC_UTIL_H
|
||||
|
||||
#include <magic/magic.h>
|
||||
#include <magic/support/SmartType.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define magicUtilLog(M) DEBUG(dbgs() << "MagicUtil: " << M << "\n")
|
||||
|
||||
class MagicUtil {
|
||||
public:
|
||||
static StringRef getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP=NULL, const std::string &baseDir="");
|
||||
static StringRef getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP=NULL);
|
||||
static StringRef getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP=NULL, const std::string &baseDir="");
|
||||
static void putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV);
|
||||
static Constant* getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes);
|
||||
static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", Instruction *InsertBefore=0);
|
||||
static GetElementPtrInst* createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
|
||||
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
|
||||
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
|
||||
static Function* getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types=NULL, unsigned size=0);
|
||||
static GlobalVariable *getStringRef(Module &M, const std::string &str);
|
||||
static GlobalVariable *getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant=true);
|
||||
static GlobalVariable *getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant=true);
|
||||
static GlobalVariable *getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant=true);
|
||||
static GlobalVariable *getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray);
|
||||
static GlobalVariable* getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant=true);
|
||||
static GlobalVariable* getShadowRef(Module &M, GlobalVariable *GV);
|
||||
static Value* getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* array, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames);
|
||||
static Value* getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName);
|
||||
static Value* getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName);
|
||||
static Value* getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName);
|
||||
static Value* getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName);
|
||||
static Value* getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName);
|
||||
static Constant* getArrayPtr(Module &M, GlobalVariable* array);
|
||||
static void insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align);
|
||||
static void insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy);
|
||||
static Function* getCalledFunctionFromCS(const CallSite &CS);
|
||||
static void replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset=0, bool removeUnusedFunction=true);
|
||||
static std::vector<Function*> getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag);
|
||||
static Function* getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag);
|
||||
static void insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore);
|
||||
static void insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore);
|
||||
static bool isShadowTag(Instruction *inst);
|
||||
static GlobalVariable* getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove);
|
||||
static void cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove);
|
||||
static bool hasAddressTaken(const GlobalValue *GV, bool includeMembers=true);
|
||||
static bool lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet);
|
||||
static Value* getStringOwner(GlobalVariable *GV);
|
||||
static Instruction* getFirstNonAllocaInst(Function* F, bool skipAllocaPoint=true);
|
||||
static void setGlobalVariableSection(GlobalVariable *GV, const std::string §ion);
|
||||
static bool getCallAnnotation(Module &M, const CallSite &CS, int *annotation);
|
||||
static bool getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation);
|
||||
static CallSite getCallSiteFromInstruction(Instruction *I);
|
||||
static AllocaInst* getAllocaInstFromArgument(Argument *argument);
|
||||
static Function* getMangledFunction(Module &M, StringRef functionName);
|
||||
static Function* getFunction(Module &M, StringRef functionName);
|
||||
static bool isCompatibleType(const Type* type1, const Type* type2);
|
||||
static void inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
|
||||
static void inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs);
|
||||
static int getPointerIndirectionLevel(const Type* type);
|
||||
static Value* getFunctionParam(Function* function, unsigned index);
|
||||
static bool isLocalConstant(Module &M, GlobalVariable *GV);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
244
minix/llvm/passes/include/magic/support/SmartType.h
Normal file
244
minix/llvm/passes/include/magic/support/SmartType.h
Normal file
|
@ -0,0 +1,244 @@
|
|||
#ifndef SMART_TYPE_H
|
||||
#define SMART_TYPE_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic/support/Backports.h>
|
||||
#include <magic/support/EDIType.h>
|
||||
#include <magic/support/TypeUtil.h>
|
||||
#include <magic/support/BitFieldAggregation.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
|
||||
#define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
|
||||
|
||||
#if HAVE_EXCEPTIONS
|
||||
#define THROW(E) throw E
|
||||
#define TRY(B) try{ B }
|
||||
#define CATCH(E, B) catch(E){ B }
|
||||
#else
|
||||
#define THROW(E) assert(0 && "throw: Exceptions disabled")
|
||||
#define TRY(B) assert(0 && "try: Exceptions disabled");
|
||||
#define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
|
||||
#endif
|
||||
|
||||
#define SmartType_assert(X) do { \
|
||||
if(!(X)) { \
|
||||
if(useExceptions) { \
|
||||
THROW(std::exception()); \
|
||||
} \
|
||||
errs() << "Assertion failed, dumping object...\n"; \
|
||||
errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
|
||||
errs() << *this; \
|
||||
} \
|
||||
assert(X); \
|
||||
} while(0)
|
||||
|
||||
class SmartType {
|
||||
public:
|
||||
SmartType(const SmartType& et);
|
||||
SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
|
||||
SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
|
||||
~SmartType();
|
||||
|
||||
SmartType& operator=(const SmartType& et);
|
||||
void cloneFrom(const SmartType& et);
|
||||
|
||||
const std::string getDescription() const;
|
||||
const SmartType* getContainedType(unsigned i) const;
|
||||
unsigned getNumContainedTypes() const;
|
||||
const DIDerivedType& getMember(unsigned i) const;
|
||||
unsigned getUnionMemberIdx() const;
|
||||
const SmartType* getTopStructType(unsigned index) const;
|
||||
|
||||
TYPECONST Type *getType() const;
|
||||
const EDIType *getEDIType() const;
|
||||
bool isTypeConsistent() const;
|
||||
bool hasInnerPointers() const;
|
||||
bool isVoidTy() const;
|
||||
bool isPrimitiveTy() const;
|
||||
bool isAggregateType() const;
|
||||
bool isFunctionTy() const;
|
||||
bool isStructTy() const;
|
||||
bool isArrayTy() const;
|
||||
bool isPointerTy() const;
|
||||
bool isOpaqueTy() const;
|
||||
bool isPaddedTy() const;
|
||||
unsigned getNumElements() const;
|
||||
bool isUseExceptions() const;
|
||||
|
||||
void verify() const;
|
||||
bool verifyTy() const;
|
||||
void print(raw_ostream &OS) const;
|
||||
bool equals(const SmartType* other, bool isDebug=false) const;
|
||||
bool hasRawTypeRepresentation() const;
|
||||
|
||||
static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
|
||||
static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
|
||||
static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
|
||||
static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
|
||||
static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
|
||||
static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
|
||||
|
||||
private:
|
||||
TYPECONST Type *type;
|
||||
EDIType aEDIType;
|
||||
bool hasExplicitContainedEDITypes;
|
||||
bool isInconsistent;
|
||||
std::vector<EDIType*> explicitContainedEDITypes;
|
||||
std::vector<BitFieldAggregation> bfas;
|
||||
bool useExceptions;
|
||||
bool rawTypeRepresentation;
|
||||
unsigned unionMemberIdx;
|
||||
static std::vector<TYPECONST Type*> equalsNestedTypes;
|
||||
static bool forceRawUnions;
|
||||
static bool forceRawBitfields;
|
||||
|
||||
void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
|
||||
void normalize();
|
||||
void flattenFunctionTy();
|
||||
int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
|
||||
bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
|
||||
|
||||
static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
|
||||
static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
|
||||
static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
|
||||
static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
|
||||
aSmartType.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
inline TYPECONST Type *SmartType::getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
inline const EDIType *SmartType::getEDIType() const {
|
||||
return &aEDIType;
|
||||
}
|
||||
|
||||
inline bool SmartType::isTypeConsistent() const {
|
||||
if(isInconsistent) {
|
||||
return false;
|
||||
}
|
||||
if(isFunctionTy() || hasRawTypeRepresentation()) {
|
||||
return true;
|
||||
}
|
||||
return isTypeConsistent(type, &aEDIType);
|
||||
}
|
||||
|
||||
inline bool SmartType::hasInnerPointers() const {
|
||||
return aEDIType.hasInnerPointers();
|
||||
}
|
||||
|
||||
inline bool SmartType::isVoidTy() const {
|
||||
return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isPrimitiveTy() const {
|
||||
if(aEDIType.isComplexFloatingPointTy()) {
|
||||
assert(type->isStructTy());
|
||||
return true;
|
||||
}
|
||||
return isTy(type->isPrimitiveType(), aEDIType.isPrimitiveType(), "isPrimitiveTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isAggregateType() const {
|
||||
return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
|
||||
}
|
||||
|
||||
inline bool SmartType::isFunctionTy() const {
|
||||
if(isOpaqueTy()) {
|
||||
return false;
|
||||
}
|
||||
return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isStructTy() const {
|
||||
if(aEDIType.isComplexFloatingPointTy()) {
|
||||
assert(type->isStructTy());
|
||||
return false;
|
||||
}
|
||||
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
|
||||
return false;
|
||||
}
|
||||
if(isOpaqueTy()) {
|
||||
return false;
|
||||
}
|
||||
return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isArrayTy() const {
|
||||
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
|
||||
return true;
|
||||
}
|
||||
if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
|
||||
return false;
|
||||
}
|
||||
return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isPointerTy() const {
|
||||
return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
|
||||
}
|
||||
|
||||
inline bool SmartType::isOpaqueTy() const {
|
||||
return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
|
||||
}
|
||||
|
||||
inline bool SmartType::isPaddedTy() const {
|
||||
if(!isAggregateType() || hasRawTypeRepresentation()) {
|
||||
return false;
|
||||
}
|
||||
return TypeUtil::isPaddedType(type);
|
||||
}
|
||||
|
||||
inline unsigned SmartType::getNumElements() const {
|
||||
if(!isArrayTy()) {
|
||||
return 0;
|
||||
}
|
||||
unsigned EDINumElements = aEDIType.getNumElements();
|
||||
unsigned numElements;
|
||||
if(type->isArrayTy()) {
|
||||
numElements = ((ArrayType*)type)->getNumElements();
|
||||
}
|
||||
else {
|
||||
assert(type->isStructTy());
|
||||
numElements = type->getNumContainedTypes();
|
||||
}
|
||||
if(numElements == 0) {
|
||||
assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
|
||||
return 0;
|
||||
}
|
||||
assert(numElements == EDINumElements);
|
||||
return numElements;
|
||||
}
|
||||
|
||||
inline bool SmartType::isUseExceptions() const {
|
||||
return useExceptions;
|
||||
}
|
||||
|
||||
inline bool SmartType::verifyTy() const {
|
||||
if(isVoidTy()) return true;
|
||||
if(isPrimitiveTy()) return true;
|
||||
if(isAggregateType()) return true;
|
||||
if(isFunctionTy()) return true;
|
||||
if(isStructTy()) return true;
|
||||
if(isArrayTy()) return true;
|
||||
if(isPointerTy()) return true;
|
||||
if(isOpaqueTy()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool SmartType::hasRawTypeRepresentation() const {
|
||||
return rawTypeRepresentation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
636
minix/llvm/passes/include/magic/support/TypeInfo.h
Normal file
636
minix/llvm/passes/include/magic/support/TypeInfo.h
Normal file
|
@ -0,0 +1,636 @@
|
|||
#ifndef TYPE_INFO_H
|
||||
#define TYPE_INFO_H
|
||||
|
||||
#include <magic/magic.h>
|
||||
#include <magic_common.h>
|
||||
#include <magic/support/SmartType.h>
|
||||
#include <magic/support/TypeUtil.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define TypeInfoErr(M) errs() << "TypeInfo: " << M << "\n"
|
||||
|
||||
#define FUNCTIONS_USE_HASH_TYPE_STRINGS 1
|
||||
#define ROOT_TYPES_HAVE_TYPE_STRINGS 0
|
||||
#define DEBUG_CAST_LOOKUPS 0
|
||||
|
||||
#define TYPEINFO_PERSISTENT 0x01
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class TypeInfo {
|
||||
public:
|
||||
TypeInfo(const SmartType *aSmartType, int persistent=0);
|
||||
TypeInfo(TYPECONST FunctionType *FT, int persistent=0);
|
||||
TypeInfo(TYPECONST PointerType *PT, int persistent=0);
|
||||
TypeInfo(TYPECONST ArrayType *AT, int persistent=0);
|
||||
TypeInfo(TYPECONST IntegerType *IT, int persistent=0);
|
||||
TypeInfo(TYPECONST StructType *OpaqueST, int persistent=0);
|
||||
void init(int persistent);
|
||||
|
||||
const SmartType *getSmartType() const;
|
||||
TYPECONST Type *getType() const;
|
||||
unsigned getNumContainedTypes() const;
|
||||
unsigned getNumChildTypes() const;
|
||||
TypeInfo *getContainedType(unsigned i) const;
|
||||
std::vector<GlobalValue*> getParents() const;
|
||||
std::string getTypeString() const;
|
||||
std::string getDescription() const;
|
||||
std::string getVerboseDescription() const;
|
||||
std::string getName() const;
|
||||
std::vector<std::string> getNames() const;
|
||||
std::string getNamesString() const;
|
||||
std::vector<std::string> getMemberNames() const;
|
||||
std::vector<int> getValueSet() const;
|
||||
std::vector<TypeInfo*> getCastTypes() const;
|
||||
unsigned getTypeID() const;
|
||||
unsigned getFlags() const;
|
||||
unsigned getBitWidth() const;
|
||||
bool equals(TYPECONST TypeInfo *other) const;
|
||||
bool hasRawTypeRepresentation() const;
|
||||
|
||||
std::string formatMemberName(const std::string &memberName, unsigned &numAnonMembers);
|
||||
void setValueSet(const std::vector<int> &valueSet);
|
||||
void setContainedTypes(const std::vector<TypeInfo*> &containedTypes);
|
||||
void addParent(GlobalValue* parent);
|
||||
void addParents(const std::vector<GlobalValue*> &parents);
|
||||
bool removeParent(GlobalValue* parent);
|
||||
bool removeAllParents();
|
||||
void setPersistent();
|
||||
bool splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken);
|
||||
|
||||
static unsigned getMaxNameLength();
|
||||
static unsigned getMaxTypeStringLength();
|
||||
static void setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes);
|
||||
static void setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes);
|
||||
|
||||
private:
|
||||
const SmartType *aSmartType;
|
||||
TYPECONST Type *aType;
|
||||
bool forceTypeDescription;
|
||||
mutable std::string typeDescription;
|
||||
std::string name;
|
||||
std::vector<std::string> names;
|
||||
std::vector<std::string> memberNames;
|
||||
std::vector<int> valueSet;
|
||||
std::vector<TypeInfo*> containedTypes;
|
||||
std::vector<GlobalValue*> parents;
|
||||
unsigned bitWidth;
|
||||
unsigned typeID;
|
||||
unsigned numElements;
|
||||
unsigned flags;
|
||||
static unsigned maxNameLength;
|
||||
static unsigned maxTypeStringLength;
|
||||
static std::map<TYPECONST Type*, std::set<int> > intCastTypes;
|
||||
static std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastTypes;
|
||||
static std::map<TYPECONST Type*, std::set<TypeInfo*> > typeMap;
|
||||
|
||||
TypeInfo() {}
|
||||
};
|
||||
|
||||
inline TypeInfo::TypeInfo(const SmartType *aSmartType, int persistent) {
|
||||
unsigned i;
|
||||
assert(aSmartType);
|
||||
this->aSmartType = aSmartType;
|
||||
this->aType = aSmartType->getType();
|
||||
bool rawTypeRepresentation = aSmartType->hasRawTypeRepresentation();
|
||||
forceTypeDescription = aSmartType->isFunctionTy();
|
||||
name = aSmartType->getEDIType()->getName();
|
||||
std::vector<StringRef> nameRefs = aSmartType->getEDIType()->getNames();
|
||||
for(i=0;i<nameRefs.size();i++) {
|
||||
if(nameRefs[i].size() > maxNameLength) {
|
||||
maxNameLength = nameRefs[i].size();
|
||||
}
|
||||
names.push_back(nameRefs[i]);
|
||||
}
|
||||
if(aSmartType->isStructTy()) {
|
||||
if(!rawTypeRepresentation) {
|
||||
const EDIType* aEDIType = aSmartType->getEDIType();
|
||||
unsigned numContainedTypes = aSmartType->getNumContainedTypes();
|
||||
unsigned numAnonMembers = 0;
|
||||
if(aEDIType->isUnionTy()) {
|
||||
assert(numContainedTypes == 1);
|
||||
i=aSmartType->getUnionMemberIdx();
|
||||
const DIDerivedType subDIType = aSmartType->getMember(i);
|
||||
memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
|
||||
}
|
||||
else {
|
||||
assert(aEDIType->isStructTy());
|
||||
i=0;
|
||||
for(;i<numContainedTypes;i++) {
|
||||
const DIDerivedType subDIType = aSmartType->getMember(i);
|
||||
memberNames.push_back(formatMemberName(subDIType.getName(), numAnonMembers));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
memberNames.push_back("raw");
|
||||
}
|
||||
}
|
||||
if(aSmartType->getEDIType()->isEnumTy()) {
|
||||
std::vector<unsigned> enumValues = aSmartType->getEDIType()->getEnumValues();
|
||||
valueSet.push_back(enumValues.size()); //push length as the first value
|
||||
for(unsigned i=0;i<enumValues.size();i++) {
|
||||
valueSet.push_back((int)enumValues[i]);
|
||||
}
|
||||
}
|
||||
bitWidth = TypeUtil::typeToBits(aSmartType->getType());
|
||||
const EDIType *aEDIType = aSmartType->getEDIType();
|
||||
typeID = 0;
|
||||
flags = 0;
|
||||
if(aSmartType->isOpaqueTy()) {
|
||||
typeID = MAGIC_TYPE_OPAQUE;
|
||||
}
|
||||
else if(aEDIType->isVoidTy()) {
|
||||
typeID = MAGIC_TYPE_VOID;
|
||||
}
|
||||
else if(aSmartType->isFunctionTy()) {
|
||||
typeID = MAGIC_TYPE_FUNCTION;
|
||||
}
|
||||
else if(aSmartType->isStructTy()) {
|
||||
if(aEDIType->isUnionTy()) {
|
||||
typeID = MAGIC_TYPE_UNION;
|
||||
}
|
||||
else if(aEDIType->isStructTy()) {
|
||||
typeID = MAGIC_TYPE_STRUCT;
|
||||
#if MAGIC_VARSIZED_STRUCTS_SUPPORT
|
||||
if(!rawTypeRepresentation) {
|
||||
assert(this->aType->getNumContainedTypes() > 0);
|
||||
TYPECONST Type *lastSubType = this->aType->getContainedType(this->aType->getNumContainedTypes()-1);
|
||||
if(lastSubType->isArrayTy() && ((ArrayType*)lastSubType)->getNumElements() <= 1) {
|
||||
flags |= MAGIC_TYPE_VARSIZE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(aSmartType->isPointerTy()) {
|
||||
typeID = MAGIC_TYPE_POINTER;
|
||||
}
|
||||
else if(aSmartType->isArrayTy()) {
|
||||
typeID = MAGIC_TYPE_ARRAY;
|
||||
}
|
||||
else if(aEDIType->isFloatingPointTy()) {
|
||||
typeID = MAGIC_TYPE_FLOAT;
|
||||
}
|
||||
else if(aEDIType->isIntegerTy()) {
|
||||
typeID = MAGIC_TYPE_INTEGER;
|
||||
}
|
||||
else if(aEDIType->isEnumTy()) {
|
||||
typeID = MAGIC_TYPE_ENUM;
|
||||
}
|
||||
else if(aEDIType->isVectorTy()) {
|
||||
typeID = MAGIC_TYPE_VECTOR;
|
||||
}
|
||||
assert(typeID);
|
||||
if(typeID == MAGIC_TYPE_INTEGER || typeID == MAGIC_TYPE_ENUM) {
|
||||
if(getNamesString().find("unsigned") != std::string::npos) {
|
||||
flags |= MAGIC_TYPE_UNSIGNED;
|
||||
}
|
||||
}
|
||||
numElements = aSmartType->getNumElements();
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(TYPECONST FunctionType *FT, int persistent) {
|
||||
assert(FT);
|
||||
aSmartType = NULL;
|
||||
aType = FT;
|
||||
forceTypeDescription = true;
|
||||
bitWidth = 0;
|
||||
typeID = MAGIC_TYPE_FUNCTION;
|
||||
numElements = 0;
|
||||
flags = MAGIC_TYPE_EXTERNAL;
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(TYPECONST PointerType *PT, int persistent) {
|
||||
assert(PT);
|
||||
aSmartType = NULL;
|
||||
aType = PT;
|
||||
forceTypeDescription = false;
|
||||
bitWidth = 0;
|
||||
typeID = MAGIC_TYPE_POINTER;
|
||||
numElements = 0;
|
||||
flags = MAGIC_TYPE_EXTERNAL;
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(TYPECONST ArrayType *AT, int persistent) {
|
||||
assert(AT);
|
||||
aSmartType = NULL;
|
||||
aType = AT;
|
||||
forceTypeDescription = false;
|
||||
bitWidth = 0;
|
||||
typeID = MAGIC_TYPE_ARRAY;
|
||||
numElements = AT->getNumElements();
|
||||
flags = MAGIC_TYPE_EXTERNAL;
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(TYPECONST IntegerType *IT, int persistent) {
|
||||
assert(IT);
|
||||
aSmartType = NULL;
|
||||
aType = IT;
|
||||
forceTypeDescription = true;
|
||||
bitWidth = IT->getBitWidth();
|
||||
typeID = MAGIC_TYPE_INTEGER;
|
||||
numElements = 0;
|
||||
flags = MAGIC_TYPE_EXTERNAL;
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline TypeInfo::TypeInfo(TYPECONST StructType *OpaqueST, int persistent) {
|
||||
assert(OpaqueST);
|
||||
assert(TypeUtil::isOpaqueTy(OpaqueST));
|
||||
aSmartType = NULL;
|
||||
aType = OpaqueST;
|
||||
forceTypeDescription = true;
|
||||
bitWidth = 0;
|
||||
typeID = MAGIC_TYPE_OPAQUE;
|
||||
numElements = 0;
|
||||
flags = MAGIC_TYPE_EXTERNAL;
|
||||
init(persistent);
|
||||
}
|
||||
|
||||
inline void TypeInfo::init(int persistent) {
|
||||
std::map<TYPECONST Type*, std::set<int> >::iterator intCastTypesIt;
|
||||
//set persistent if necessary
|
||||
if(persistent) {
|
||||
setPersistent();
|
||||
}
|
||||
//initialize value set for pointers casted to int
|
||||
if(aType->isPointerTy()) {
|
||||
intCastTypesIt = intCastTypes.find(aType);
|
||||
if(intCastTypesIt != intCastTypes.end()) {
|
||||
std::set<int> &pointerValues = intCastTypesIt->second;
|
||||
assert(pointerValues.size() > 0);
|
||||
flags |= MAGIC_TYPE_INT_CAST;
|
||||
if(pointerValues.size() > 1 || *(pointerValues.begin()) != 0) {
|
||||
valueSet.push_back(pointerValues.size()); //push length as the first value
|
||||
for(std::set<int>::iterator it=pointerValues.begin() ; it != pointerValues.end(); it++) {
|
||||
assert(*it != 0);
|
||||
valueSet.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//adjust flags
|
||||
bool hasInnerPointers = aSmartType ? aSmartType->hasInnerPointers() : TypeUtil::hasInnerPointers(aType);
|
||||
if(!hasInnerPointers) {
|
||||
flags |= MAGIC_TYPE_NO_INNER_PTRS;
|
||||
}
|
||||
}
|
||||
|
||||
inline const SmartType *TypeInfo::getSmartType() const {
|
||||
return aSmartType;
|
||||
}
|
||||
|
||||
inline TYPECONST Type *TypeInfo::getType() const {
|
||||
return aType;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getNumContainedTypes() const {
|
||||
return containedTypes.size();
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getNumChildTypes() const {
|
||||
return typeID == MAGIC_TYPE_ARRAY ? numElements : containedTypes.size();
|
||||
}
|
||||
|
||||
inline TypeInfo *TypeInfo::getContainedType(unsigned i) const {
|
||||
assert(i<containedTypes.size());
|
||||
return containedTypes[i];
|
||||
}
|
||||
|
||||
inline std::vector<GlobalValue*> TypeInfo::getParents() const {
|
||||
return parents;
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::getTypeString() const {
|
||||
std::string typeString = forceTypeDescription || aType->getNumContainedTypes() == 0 ? getDescription() : "";
|
||||
if(MAGIC_SHRINK_TYPE_STR && typeString.size() > MAGIC_MAX_TYPE_STR_LEN) {
|
||||
typeString = typeString.substr(0, MAGIC_MAX_TYPE_STR_LEN-3) + "...";
|
||||
}
|
||||
if(typeString.size() > maxTypeStringLength) {
|
||||
maxTypeStringLength = typeString.size();
|
||||
}
|
||||
return typeString;
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::getDescription() const {
|
||||
if(typeDescription.size() == 0) {
|
||||
if(aType->isFunctionTy() && FUNCTIONS_USE_HASH_TYPE_STRINGS) {
|
||||
unsigned hash = TypeUtil::getHash(aType);
|
||||
raw_string_ostream ostream(typeDescription);
|
||||
ostream << "hash_" << hash;
|
||||
ostream.flush();
|
||||
}
|
||||
else {
|
||||
typeDescription = TypeUtil::getDescription(aType);
|
||||
}
|
||||
}
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::getVerboseDescription() const {
|
||||
return aSmartType ? aSmartType->getDescription() : getDescription();
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> TypeInfo::getNames() const {
|
||||
return names;
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::getNamesString() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
for(unsigned i=0;i<names.size();i++) {
|
||||
if(i>0) ostream << "|";
|
||||
ostream << names[i];
|
||||
}
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> TypeInfo::getMemberNames() const {
|
||||
for(unsigned i=0;i<memberNames.size();i++) {
|
||||
if(memberNames[i].size() > maxNameLength) {
|
||||
maxNameLength = memberNames[i].size();
|
||||
}
|
||||
}
|
||||
return memberNames;
|
||||
}
|
||||
|
||||
inline std::vector<int> TypeInfo::getValueSet() const {
|
||||
return valueSet;
|
||||
}
|
||||
|
||||
inline std::vector<TypeInfo*> TypeInfo::getCastTypes() const {
|
||||
std::vector<TypeInfo*> castTypes;
|
||||
std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastTypesIt;
|
||||
std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
|
||||
if(!aType->isPointerTy()) {
|
||||
return castTypes;
|
||||
}
|
||||
//XXX to-do: match only original struct name during lookup by looking at the original bitcast instruction
|
||||
//the following lookups do not distinguish between struct x = {18} and struct y = {i8}
|
||||
//the number of false positives generated seems to be fairly small, anyway
|
||||
bitCastTypesIt = bitCastTypes.find(aType);
|
||||
if(bitCastTypesIt == bitCastTypes.end()) {
|
||||
return castTypes;
|
||||
}
|
||||
std::set<TYPECONST Type*> bitCastSet = bitCastTypesIt->second;
|
||||
#if MAGIC_INDEX_TRANSITIVE_BIT_CASTS
|
||||
std::vector<TYPECONST Type*> bitCasts;
|
||||
for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
|
||||
bitCasts.push_back(*it);
|
||||
}
|
||||
while(!bitCasts.empty()) {
|
||||
TYPECONST Type* bcType = bitCasts.front();
|
||||
bitCasts.erase(bitCasts.begin());
|
||||
bitCastTypesIt = bitCastTypes.find(bcType);
|
||||
if(bitCastTypesIt != bitCastTypes.end()) {
|
||||
std::set<TYPECONST Type*> set = bitCastTypesIt->second;
|
||||
for(std::set<TYPECONST Type*>::iterator it=set.begin();it!=set.end();it++) {
|
||||
unsigned bitCastSetSize = bitCastSet.size();
|
||||
TYPECONST Type *newBcType = *it;
|
||||
if(newBcType == aType) {
|
||||
continue;
|
||||
}
|
||||
bitCastSet.insert(newBcType);
|
||||
if(bitCastSet.size() != bitCastSetSize) {
|
||||
bitCasts.push_back(newBcType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG_CAST_LOOKUPS
|
||||
if(aType->getContainedType(0)->isStructTy()) {
|
||||
TypeInfoErr("--- type is struct* " << getContainedType(0)->getName());
|
||||
}
|
||||
else if(aType->getContainedType(0)->isPointerTy() && aType->getContainedType(0)->getContainedType(0)->isStructTy()) {
|
||||
TypeInfoErr("--- type is struct** " << getContainedType(0)->getContainedType(0)->getName());
|
||||
}
|
||||
else {
|
||||
TypeInfoErr("--- type is " << getDescription());
|
||||
}
|
||||
#endif
|
||||
|
||||
for(std::set<TYPECONST Type*>::iterator it=bitCastSet.begin();it!=bitCastSet.end();it++) {
|
||||
TYPECONST Type* type = *it;
|
||||
assert(type->isPointerTy());
|
||||
typeMapIt = typeMap.find(type->getContainedType(0));
|
||||
if(typeMapIt == typeMap.end()) {
|
||||
|
||||
#if DEBUG_CAST_LOOKUPS
|
||||
TypeInfoErr("*** cast target type not found: " << TypeUtil::getDescription(type->getContainedType(0)));
|
||||
#endif
|
||||
|
||||
continue;
|
||||
}
|
||||
std::set<TypeInfo*> *typeInfoSet = &(typeMapIt->second);
|
||||
for(std::set<TypeInfo*>::iterator it2=typeInfoSet->begin();it2!=typeInfoSet->end();it2++) {
|
||||
TypeInfo* typeInfo = *it2;
|
||||
assert(typeInfo->getType() != getType()->getContainedType(0));
|
||||
|
||||
#if DEBUG_CAST_LOOKUPS
|
||||
if(typeInfo->getType()->isStructTy()) {
|
||||
TypeInfoErr(">>> cast target type info is struct " << typeInfo->getName());
|
||||
}
|
||||
else if(typeInfo->getType()->isPointerTy() && typeInfo->getType()->getContainedType(0)->isStructTy()) {
|
||||
TypeInfoErr(">>> cast target type info is struct* " << typeInfo->getContainedType(0)->getName());
|
||||
}
|
||||
else {
|
||||
TypeInfoErr(">>> cast target type info is " << typeInfo->getDescription());
|
||||
}
|
||||
#endif
|
||||
castTypes.push_back(typeInfo);
|
||||
|
||||
#if MAGIC_COMPACT_COMP_TYPES
|
||||
/* This is safe as long as we check for compatible (LLVM) types at runtime. */
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(castTypes.size() > 0) { //push delimiter
|
||||
castTypes.push_back(NULL);
|
||||
}
|
||||
return castTypes;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getTypeID() const {
|
||||
return typeID;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getFlags() const {
|
||||
return flags;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getBitWidth() const {
|
||||
return bitWidth;
|
||||
}
|
||||
|
||||
inline bool TypeInfo::equals(TYPECONST TypeInfo *other) const {
|
||||
if(aSmartType && other->getSmartType()) {
|
||||
return aSmartType->equals(other->getSmartType());
|
||||
}
|
||||
return (flags & (~MAGIC_TYPE_IS_ROOT)) == (other->getFlags() & (~MAGIC_TYPE_IS_ROOT))
|
||||
&& !getDescription().compare(other->getDescription());
|
||||
}
|
||||
|
||||
inline bool TypeInfo::hasRawTypeRepresentation() const {
|
||||
return aSmartType && aSmartType->hasRawTypeRepresentation();
|
||||
}
|
||||
|
||||
inline std::string TypeInfo::formatMemberName(const std::string &memberName, unsigned &numAnonMembers) {
|
||||
if (memberName.compare("")) {
|
||||
return memberName;
|
||||
}
|
||||
std::string name(memberName);
|
||||
raw_string_ostream ostream(name);
|
||||
ostream << MAGIC_ANON_MEMBER_PREFIX << "." << (numAnonMembers+1);
|
||||
ostream.flush();
|
||||
numAnonMembers++;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void TypeInfo::setValueSet(const std::vector<int> &valueSet) {
|
||||
this->valueSet = valueSet;
|
||||
}
|
||||
|
||||
inline void TypeInfo::setContainedTypes(const std::vector<TypeInfo*> &containedTypes) {
|
||||
this->containedTypes = containedTypes;
|
||||
}
|
||||
|
||||
inline void TypeInfo::addParent(GlobalValue* parent) {
|
||||
assert((typeID == MAGIC_TYPE_FUNCTION && dyn_cast<Function>(parent))
|
||||
|| (typeID != MAGIC_TYPE_FUNCTION && dyn_cast<GlobalVariable>(parent)));
|
||||
this->parents.push_back(parent);
|
||||
flags |= MAGIC_TYPE_IS_ROOT;
|
||||
|
||||
#if ROOT_TYPES_HAVE_TYPE_STRINGS
|
||||
forceTypeDescription = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void TypeInfo::addParents(const std::vector<GlobalValue*> &parents) {
|
||||
for(unsigned i=0;i<parents.size();i++) {
|
||||
addParent(parents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool TypeInfo::removeParent(GlobalValue* parent)
|
||||
{
|
||||
std::vector<GlobalValue*> originalParents = this->parents;
|
||||
this->parents.clear();
|
||||
for(unsigned i=0;i<originalParents.size();i++) {
|
||||
if(originalParents[i] != parent) {
|
||||
this->parents.push_back(originalParents[i]);
|
||||
}
|
||||
}
|
||||
int sizeDiff = originalParents.size() - this->parents.size();
|
||||
assert(sizeDiff == 0 || sizeDiff == 1);
|
||||
return (sizeDiff == 1);
|
||||
}
|
||||
|
||||
inline bool TypeInfo::removeAllParents()
|
||||
{
|
||||
if(this->parents.size() > 0) {
|
||||
this->parents.clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void TypeInfo::setPersistent() {
|
||||
std::map<TYPECONST Type*, std::set<TypeInfo*> >::iterator typeMapIt;
|
||||
typeMapIt = typeMap.find(aType);
|
||||
if(typeMapIt == typeMap.end()) {
|
||||
std::set<TypeInfo*> set;
|
||||
set.insert(this);
|
||||
typeMap.insert(std::pair<TYPECONST Type*, std::set<TypeInfo*> >(aType, set));
|
||||
}
|
||||
else {
|
||||
std::set<TypeInfo*> *set;
|
||||
set = &(typeMapIt->second);
|
||||
set->insert(this);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool TypeInfo::splitByParentValueSet(std::vector<TypeInfo*> &splitTypeInfos, std::set<GlobalVariable*> &globalVariablesWithAddressTaken) {
|
||||
std::map<std::vector<int>, std::vector<GlobalVariable*> > valueSetMap;
|
||||
std::map<std::vector<int>, std::vector<GlobalVariable*> >::iterator valueSetMapIt;
|
||||
std::vector<int> valueSet;
|
||||
splitTypeInfos.push_back(this);
|
||||
if(!isa<IntegerType>(aType)) {
|
||||
return false;
|
||||
}
|
||||
assert(valueSet.size() == 0);
|
||||
for(unsigned i=0;i<parents.size();i++) {
|
||||
if(GlobalVariable *GV = dyn_cast<GlobalVariable>(parents[i])) {
|
||||
bool hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
|
||||
if(hasAddressTaken) {
|
||||
continue;
|
||||
}
|
||||
valueSet.clear();
|
||||
bool valueSetFound = MagicUtil::lookupValueSet(GV, valueSet);
|
||||
if(!valueSetFound) {
|
||||
continue;
|
||||
}
|
||||
valueSetMapIt = valueSetMap.find(valueSet);
|
||||
if(valueSetMapIt == valueSetMap.end()) {
|
||||
std::vector<GlobalVariable*> vector;
|
||||
valueSetMap.insert(std::pair<std::vector<int>, std::vector<GlobalVariable*> >(valueSet, vector));
|
||||
valueSetMapIt = valueSetMap.find(valueSet);
|
||||
assert(valueSetMapIt != valueSetMap.end());
|
||||
}
|
||||
std::vector<GlobalVariable*> *globalsVector = &valueSetMapIt->second;
|
||||
globalsVector->push_back(GV);
|
||||
}
|
||||
}
|
||||
if(valueSetMap.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
for(valueSetMapIt = valueSetMap.begin(); valueSetMapIt!=valueSetMap.end(); valueSetMapIt++) {
|
||||
const std::vector<int> &values = valueSetMapIt->first;
|
||||
const std::vector<GlobalVariable*> &globalVariables = valueSetMapIt->second;
|
||||
TypeInfo *aTypeInfo = new TypeInfo(*this);
|
||||
aTypeInfo->setValueSet(values);
|
||||
aTypeInfo->removeAllParents();
|
||||
for(unsigned i=0;i<globalVariables.size();i++) {
|
||||
GlobalVariable* GV = globalVariables[i];
|
||||
bool parentRemoved = this->removeParent(GV);
|
||||
assert(parentRemoved);
|
||||
aTypeInfo->addParent(GV);
|
||||
}
|
||||
splitTypeInfos.push_back(aTypeInfo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getMaxNameLength() {
|
||||
return TypeInfo::maxNameLength;
|
||||
}
|
||||
|
||||
inline unsigned TypeInfo::getMaxTypeStringLength() {
|
||||
return TypeInfo::maxTypeStringLength;
|
||||
}
|
||||
|
||||
inline void TypeInfo::setIntCastTypes(std::map<TYPECONST Type*, std::set<int> > &intCastTypes) {
|
||||
TypeInfo::intCastTypes = intCastTypes;
|
||||
}
|
||||
|
||||
inline void TypeInfo::setBitCastTypes(std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastTypes) {
|
||||
TypeInfo::bitCastTypes = bitCastTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
52
minix/llvm/passes/include/magic/support/TypeUtil.h
Normal file
52
minix/llvm/passes/include/magic/support/TypeUtil.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef TYPE_UTIL_H
|
||||
#define TYPE_UTIL_H
|
||||
|
||||
#include <pass.h>
|
||||
#include <magic/support/EDIType.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define TypeUtilLog(M) DEBUG(dbgs() << "TypeUtil: " << M << "\n")
|
||||
|
||||
class TypeUtil {
|
||||
public:
|
||||
static int VERBOSE_LEVEL;
|
||||
static int PRINT_SKIP_UNIONS;
|
||||
static int PRINT_SKIP_STRUCTS;
|
||||
static int PRINT_USE_BUILTIN_PRINTING;
|
||||
static int PRINT_MULTI_NAMES;
|
||||
static const unsigned TYPE_STRUCT = 0x01;
|
||||
static const unsigned TYPE_UNION = 0x02;
|
||||
static const unsigned TYPE_ANONYMOUS = 0x04;
|
||||
static const unsigned TYPE_UNNAMED = 0x08;
|
||||
|
||||
static bool isPaddedType(TYPECONST Type *type);
|
||||
|
||||
static TYPECONST Type* lookupTopStructType(TYPECONST Type *type, unsigned index);
|
||||
static void parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags);
|
||||
static int findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept);
|
||||
static TYPECONST Type* getRecursiveElementType(TYPECONST Type *type);
|
||||
static TYPECONST Type* getArrayFreePointerType(TYPECONST Type *type);
|
||||
static bool hasInnerPointers(TYPECONST Type *type);
|
||||
static bool isArrayAsStructTy(TYPECONST Type *type);
|
||||
static bool isOpaqueTy(TYPECONST Type *type);
|
||||
|
||||
static unsigned getHash(TYPECONST Type* type);
|
||||
static const std::string getDescription(TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
|
||||
static const std::string getDescription(const EDIType* aEDIType);
|
||||
static const std::string getDescription(TYPECONST Type* type, const EDIType* aEDIType, size_t max_chars = 0, size_t max_levels = 0);
|
||||
static const std::string getFormattedDescription(std::string &description);
|
||||
static void printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length);
|
||||
static void printTypeString(raw_ostream &OS, TYPECONST Type* type, size_t max_chars = 0, size_t max_levels = 0);
|
||||
static unsigned typeToBits(TYPECONST Type *type);
|
||||
};
|
||||
|
||||
inline bool TypeUtil::isOpaqueTy(TYPECONST Type *type) {
|
||||
return PassUtil::isOpaqueTy(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
minix/llvm/passes/include/magic/support/VariableRefs.h
Normal file
30
minix/llvm/passes/include/magic/support/VariableRefs.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef VARIABLE_REFS_H
|
||||
#define VARIABLE_REFS_H
|
||||
|
||||
#include <pass.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class VariableRefs {
|
||||
public:
|
||||
VariableRefs();
|
||||
|
||||
bool isUnnecessaryInstruction(Instruction* inst) const;
|
||||
Instruction* getInstruction() const;
|
||||
bool isInstructionInEntryBlock() const;
|
||||
|
||||
void addInstruction(Instruction* inst);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
Instruction* instruction;
|
||||
bool instructionInEntryBlock;
|
||||
|
||||
void setFunctionEntryInstruction(Function* function);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,8 +2,8 @@
|
|||
#ifndef _PASS_H
|
||||
#define _PASS_H
|
||||
|
||||
#import <set>
|
||||
#import <map>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <llvm/Pass.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
2877
minix/llvm/passes/magic/MagicPass.cpp
Normal file
2877
minix/llvm/passes/magic/MagicPass.cpp
Normal file
File diff suppressed because it is too large
Load diff
6
minix/llvm/passes/magic/Makefile
Normal file
6
minix/llvm/passes/magic/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
PASSNAME = magic
|
||||
|
||||
OBJS = support/Backports.o support/EDIType.o support/TypeUtil.o support/BitFieldAggregation.o support/SmartType.o support/VariableRefs.o support/MagicUtil.o MagicPass.o
|
||||
HEADERS = $(wildcard ../include/magic/support/*.h)
|
||||
|
||||
include ../Makefile.inc
|
172
minix/llvm/passes/magic/support/Backports.cpp
Normal file
172
minix/llvm/passes/magic/support/Backports.cpp
Normal file
|
@ -0,0 +1,172 @@
|
|||
#include <pass.h>
|
||||
|
||||
#include <magic/support/Backports.h>
|
||||
#include <magic/support/EDIType.h>
|
||||
#include <magic/support/SmartType.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Find the debug info descriptor corresponding to this global variable.
|
||||
Value *Backports::findDbgGlobalDeclare(GlobalVariable *V) {
|
||||
return PassUtil::findDbgGlobalDeclare(V);
|
||||
}
|
||||
|
||||
/// Find the debug info descriptor corresponding to this function.
|
||||
Value *Backports::findDbgSubprogramDeclare(Function *V) {
|
||||
return PassUtil::findDbgSubprogramDeclare(V);
|
||||
}
|
||||
|
||||
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
|
||||
/// It looks through pointer casts too.
|
||||
const DbgDeclareInst *Backports::findDbgDeclare(const Value *V) {
|
||||
V = V->stripPointerCasts();
|
||||
|
||||
if (!isa<Instruction>(V) && !isa<Argument>(V))
|
||||
return 0;
|
||||
|
||||
const Function *F = NULL;
|
||||
if (const Instruction *I = dyn_cast<Instruction>(V))
|
||||
F = I->getParent()->getParent();
|
||||
else if (const Argument *A = dyn_cast<Argument>(V))
|
||||
F = A->getParent();
|
||||
|
||||
for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
|
||||
for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end();
|
||||
BI != BE; ++BI)
|
||||
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
|
||||
if (DDI->getAddress() == V)
|
||||
return DDI;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
|
||||
/// alloca 'V', if any.
|
||||
DbgDeclareInst *Backports::FindAllocaDbgDeclare(Value *V) {
|
||||
#if LLVM_VERSION >= 33
|
||||
if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V))
|
||||
for (Value::use_iterator UI = DebugNode->use_begin(),
|
||||
E = DebugNode->use_end(); UI != E; ++UI)
|
||||
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(*UI))
|
||||
return DDI;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
|
||||
///
|
||||
/// There is an unfixed bug (http://llvm.org/bugs/show_bug.cgi?id=10887)
|
||||
/// that drops debug information references for local variables at linking time.
|
||||
/// This is way the method FindAllocaDbgDeclare() will always return NULL and
|
||||
/// we need to resort to some ugly workaround.
|
||||
///
|
||||
AllocaInst *AI = dyn_cast<AllocaInst>(V);
|
||||
if(!AI) {
|
||||
return NULL;
|
||||
}
|
||||
BasicBlock *varParent = AI->getParent();
|
||||
Function *varFunc = varParent->getParent();
|
||||
if(!AI->hasName() || !AI->getName().compare("retval")) {
|
||||
return NULL;
|
||||
}
|
||||
StringRef varName = AI->getName();
|
||||
bool isInlinedVar = false;
|
||||
bool isScopedVar = false;
|
||||
DIType aDIType, aAddrDIType, tmpDIType;
|
||||
DbgDeclareInst *DDI = NULL, *addrDDI = NULL;
|
||||
SmallVector< StringRef, 8 > vector;
|
||||
varName.split(vector, ".");
|
||||
if(vector.size() >= 2 && vector[1][0] == 'i') {
|
||||
isInlinedVar = true;
|
||||
varName = vector[0];
|
||||
}
|
||||
if(!isInlinedVar) {
|
||||
//for non-inlined variables we have to look in the first bb first.
|
||||
for(BasicBlock::iterator i=varParent->begin(), e=varParent->end();i!=e;i++) {
|
||||
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(i)) {
|
||||
MDNode *node = DI->getVariable();
|
||||
assert(node);
|
||||
DIVariable DIV(node);
|
||||
if(!DIV.getName().compare(varName)) {
|
||||
aDIType = DIV.getType();
|
||||
DDI = DI;
|
||||
break;
|
||||
}
|
||||
StringRef addrVarName(DIV.getName().str() + "_addr");
|
||||
if(!addrVarName.compare(varName)) {
|
||||
aAddrDIType = DIV.getType();
|
||||
addrDDI = DI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!DDI && !addrDDI) {
|
||||
//not found? probably a scoped variable, look anywhere else.
|
||||
isScopedVar = true;
|
||||
}
|
||||
}
|
||||
if(isInlinedVar || isScopedVar) {
|
||||
//for inlined/scoped variables we have to look everywhere in the function and name clashing could also occur.
|
||||
bool isDuplicate = false;
|
||||
for (inst_iterator it = inst_begin(varFunc), et = inst_end(varFunc); it != et; ++it) {
|
||||
Instruction *inst = &(*it);
|
||||
if(DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(inst)) {
|
||||
MDNode *node = DI->getVariable();
|
||||
assert(node);
|
||||
DIVariable DIV(node);
|
||||
StringRef addrVarName(DIV.getName().str() + "_addr");
|
||||
if(!DIV.getName().compare(varName) || !addrVarName.compare(varName)) {
|
||||
tmpDIType = DIV.getType();
|
||||
EDIType tmpEDIType(tmpDIType);
|
||||
if(!SmartType::isTypeConsistent(AI->getAllocatedType(), &tmpEDIType)) {
|
||||
continue;
|
||||
}
|
||||
bool skipDIType = false;
|
||||
if(DDI) {
|
||||
EDIType aEDIType(aDIType);
|
||||
skipDIType = true;
|
||||
if(!aEDIType.equals(&tmpEDIType)) {
|
||||
isDuplicate = true;
|
||||
}
|
||||
}
|
||||
if(addrDDI) {
|
||||
EDIType aAddrEDIType(aAddrDIType);
|
||||
skipDIType = true;
|
||||
if(!aAddrEDIType.equals(&tmpEDIType)) {
|
||||
isDuplicate = true;
|
||||
}
|
||||
}
|
||||
if(!skipDIType && !DIV.getName().compare(varName)) {
|
||||
aDIType = tmpDIType;
|
||||
DDI = DI;
|
||||
continue;
|
||||
}
|
||||
if(!skipDIType && !addrVarName.compare(varName)) {
|
||||
aAddrDIType = tmpDIType;
|
||||
addrDDI = DI;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isDuplicate) {
|
||||
//name clashing problem with inline/scoped variables, pretend nothing was found
|
||||
DDI = NULL;
|
||||
addrDDI = NULL;
|
||||
}
|
||||
}
|
||||
if(!DDI && !addrDDI) {
|
||||
return (DbgDeclareInst*)-1;
|
||||
}
|
||||
assert((DDI && !addrDDI) || (!DDI && addrDDI));
|
||||
DDI = DDI ? DDI : addrDDI;
|
||||
return DDI;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
171
minix/llvm/passes/magic/support/BitFieldAggregation.cpp
Normal file
171
minix/llvm/passes/magic/support/BitFieldAggregation.cpp
Normal file
|
@ -0,0 +1,171 @@
|
|||
#include <magic/support/BitFieldAggregation.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define DEBUG_BFA 0
|
||||
|
||||
#define BitFieldAggregation_assert_or_return(R,RV,T,ET,X) do { \
|
||||
if(!(X)) { \
|
||||
if(R) return RV; \
|
||||
errs() << "Assertion failed, dumping types...\n"; \
|
||||
errs() << TypeUtil::getDescription(T, ET); \
|
||||
} \
|
||||
assert(X); \
|
||||
} while(0)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Constructors, destructor, and operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
BitFieldAggregation::BitFieldAggregation(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
|
||||
init(type, EDITypes, typeIndex, EDITypeIndex, members, counter);
|
||||
}
|
||||
|
||||
BitFieldAggregation::BitFieldAggregation() {
|
||||
type = NULL;
|
||||
typeIndex = 0;
|
||||
EDITypeIndex = 0;
|
||||
name = "";
|
||||
}
|
||||
|
||||
void BitFieldAggregation::init(TYPECONST Type* type, std::vector<EDIType> EDITypes, unsigned typeIndex, unsigned EDITypeIndex, std::vector<DIDerivedType> members, unsigned counter) {
|
||||
assert(members.size() == EDITypes.size());
|
||||
assert(typeIndex <= EDITypeIndex);
|
||||
size = members.size();
|
||||
assert(size > 0);
|
||||
|
||||
this->type = type;
|
||||
this->EDITypes = EDITypes;
|
||||
this->typeIndex = typeIndex;
|
||||
this->EDITypeIndex = EDITypeIndex;
|
||||
this->members = members;
|
||||
raw_string_ostream ostream(name);
|
||||
ostream << bfaNamePrefix << counter;
|
||||
ostream.flush();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Getters
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const std::string BitFieldAggregation::getDescription() const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
ostream << "[\nname = " << name << "\nmembers = ";
|
||||
for(unsigned i=0;i<size;i++) {
|
||||
ostream << (i==0 ? "" : ", ") << members[i].getName();
|
||||
}
|
||||
ostream << "\ntype = \n" << TypeUtil::getDescription(getType());
|
||||
std::vector<EDIType> EDITypes = getEDITypes();
|
||||
for(unsigned i=0;i<EDITypes.size();i++) {
|
||||
ostream << "\nEDIType" << i << " =\n" << TypeUtil::getDescription(&EDITypes[i]);
|
||||
}
|
||||
ostream << "\n]";
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool BitFieldAggregation::getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError) {
|
||||
std::vector<BitFieldAggregation> emptyBfas;
|
||||
if(!hasBitFields(type, aEDIType)) {
|
||||
return true;
|
||||
}
|
||||
unsigned typeIndex = 0;
|
||||
unsigned EDITypeIndex = 0;
|
||||
unsigned typeContainedTypes = type->getNumContainedTypes();
|
||||
unsigned aEDITypeContainedTypes = aEDIType->getNumContainedTypes();
|
||||
unsigned counter = 1;
|
||||
const EDIType privateEDIType(*aEDIType);
|
||||
aEDIType = &privateEDIType;
|
||||
while(typeIndex < typeContainedTypes) {
|
||||
TYPECONST Type *containedType = type->getContainedType(typeIndex);
|
||||
if(EDITypeIndex >= aEDITypeContainedTypes && typeIndex == typeContainedTypes-1 && TypeUtil::isPaddedType(type)) {
|
||||
break;
|
||||
}
|
||||
BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, EDITypeIndex < aEDITypeContainedTypes);
|
||||
const EDIType containedEDIType = aEDIType->getContainedType(EDITypeIndex);
|
||||
unsigned typeBits = TypeUtil::typeToBits(containedType);
|
||||
if(typeBits > 0 && containedEDIType.isIntegerTy()) {
|
||||
unsigned EDITypeBits = aEDIType->getMember(EDITypeIndex).getSizeInBits();
|
||||
assert(typeBits >= EDITypeBits);
|
||||
if(typeBits > EDITypeBits) {
|
||||
unsigned lastTypeIndex = typeIndex;
|
||||
unsigned lastEDITypeIndex = EDITypeIndex;
|
||||
while(lastEDITypeIndex+1 < aEDITypeContainedTypes && isBitField(type, aEDIType, lastEDITypeIndex+1)) { // grab all the bitfields following the first one found
|
||||
lastEDITypeIndex++;
|
||||
EDITypeBits += aEDIType->getMember(lastEDITypeIndex).getSizeInBits();
|
||||
}
|
||||
while(lastTypeIndex+1 < typeContainedTypes && EDITypeBits > typeBits) { // grab all the necessary fields to cover all the bits found in the bitfields
|
||||
lastTypeIndex++;
|
||||
typeBits += TypeUtil::typeToBits(type->getContainedType(lastTypeIndex));
|
||||
}
|
||||
BitFieldAggregation *bfa = BitFieldAggregation::getBitFieldAggregation(type, aEDIType, returnOnError, typeIndex, EDITypeIndex, lastTypeIndex, lastEDITypeIndex, counter++);
|
||||
BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, bfa != NULL);
|
||||
if(bfa->getSize() > 1) {
|
||||
//we don't care about single-element aggregates
|
||||
bfas.push_back(*bfa);
|
||||
}
|
||||
typeIndex++;
|
||||
EDITypeIndex += bfa->getSize();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
typeIndex++;
|
||||
EDITypeIndex++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BitFieldAggregation *BitFieldAggregation::getBitFieldAggregation(TYPECONST Type *type, const EDIType *aEDIType, bool returnOnError, unsigned typeIndex, unsigned EDITypeIndex, unsigned lastTypeIndex, unsigned lastEDITypeIndex, unsigned counter) {
|
||||
static BitFieldAggregation bfa;
|
||||
TYPECONST Type *containedType = type->getContainedType(typeIndex);
|
||||
unsigned typeBits = TypeUtil::typeToBits(containedType);
|
||||
assert(typeBits > 0);
|
||||
unsigned nextTypeBits = 0;
|
||||
if (typeIndex < lastTypeIndex) {
|
||||
nextTypeBits = TypeUtil::typeToBits(type->getContainedType(typeIndex+1));
|
||||
}
|
||||
const int maxNumMembers = (lastEDITypeIndex - EDITypeIndex) - (lastTypeIndex - typeIndex) + 1;
|
||||
unsigned index = EDITypeIndex;
|
||||
std::vector<DIDerivedType> members;
|
||||
std::vector<EDIType> containedEDITypes;
|
||||
|
||||
BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, maxNumMembers > 0);
|
||||
#if DEBUG_BFA
|
||||
BitFieldAggregationErr("getBitFieldAggregation(): typeIndex = " << typeIndex << ", EDITypeIndex = " << EDITypeIndex << ", maxNumMembers = " << maxNumMembers);
|
||||
BitFieldAggregationErr("getBitFieldAggregation(): lastTypeIndex = " << lastTypeIndex << ", lastEDITypeIndex = " << lastEDITypeIndex);
|
||||
BitFieldAggregationErr("getBitFieldAggregation(): " << TypeUtil::getDescription(type) << " VS " << TypeUtil::getDescription(aEDIType));
|
||||
#endif
|
||||
while(index <= lastEDITypeIndex && members.size() < (unsigned)maxNumMembers) {
|
||||
const EDIType containedEDIType = aEDIType->getContainedType(index);
|
||||
#if DEBUG_BFA
|
||||
BitFieldAggregationErr("Examining type " << TypeUtil::getDescription(&containedEDIType));
|
||||
#endif
|
||||
BitFieldAggregation_assert_or_return(returnOnError, NULL, type, aEDIType, containedEDIType.isIntegerTy());
|
||||
DIDerivedType member = aEDIType->getMember(index);
|
||||
unsigned EDITypeBits = member.getSizeInBits();
|
||||
#if DEBUG_BFA
|
||||
BitFieldAggregationErr("Type bits = " << typeBits << ", next type bits = " << nextTypeBits << ", index = " << index);
|
||||
BitFieldAggregationErr("This is member " << member.getName() << " with bits " << EDITypeBits);
|
||||
#endif
|
||||
if((index > EDITypeIndex && EDITypeBits == nextTypeBits) || EDITypeBits > typeBits) {
|
||||
break;
|
||||
}
|
||||
typeBits -= EDITypeBits;
|
||||
members.push_back(member);
|
||||
containedEDITypes.push_back(containedEDIType);
|
||||
index++;
|
||||
}
|
||||
bfa.init(containedType, containedEDITypes, typeIndex, EDITypeIndex, members, counter);
|
||||
return &bfa;
|
||||
}
|
||||
|
||||
std::string BitFieldAggregation::bfaNamePrefix = BFA_NAME_PREFIX;
|
||||
|
||||
}
|
520
minix/llvm/passes/magic/support/EDIType.cpp
Normal file
520
minix/llvm/passes/magic/support/EDIType.cpp
Normal file
|
@ -0,0 +1,520 @@
|
|||
|
||||
#include <magic/support/EDIType.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define DEBUG_EDI_EQUALS 0
|
||||
int debugEDIEquals = 0;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Constructors, destructor, and operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
EDIType::EDIType(const MDNode *N, bool norm, bool checkOpaqueTypes) : aDIType(N) {
|
||||
init(norm, checkOpaqueTypes);
|
||||
}
|
||||
|
||||
EDIType::EDIType(bool norm, bool checkOpaqueTypes) : aDIType() {
|
||||
init(norm, checkOpaqueTypes);
|
||||
}
|
||||
|
||||
EDIType::EDIType(const DIType aDIType, bool norm, bool checkOpaqueTypes) : aDIType(aDIType) {
|
||||
init(norm, checkOpaqueTypes);
|
||||
}
|
||||
|
||||
bool EDIType::operator == (const EDIType& aEDIType) const {
|
||||
const DIType oDIType = *(aEDIType.getDIType());
|
||||
return (aDIType == oDIType);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Getters
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const std::string EDIType::getDescription(int skipUnions, int skipStructs, int allowMultiNames) const {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
printDescription(ostream, skipUnions, skipStructs, allowMultiNames);
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
const EDIType& EDIType::getContainedType(unsigned i, bool norm) const {
|
||||
static EDIType subType;
|
||||
EDIType_assert(!isBasicType() && !isVoidTy() && !isEnumTy());
|
||||
bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
|
||||
if(isDerivedType() || isArrayOrVectorTy) {
|
||||
EDIType_assert(i == 0);
|
||||
if(isArrayOrVectorTy && getCurrentDimension() < getNumDimensions()-1) {
|
||||
subType = *this;
|
||||
subType.setCurrentDimension(getCurrentDimension() + 1);
|
||||
}
|
||||
else {
|
||||
subType = getTypeDerivedFrom();
|
||||
}
|
||||
return subType;
|
||||
}
|
||||
DIArray aDIArray = getTypeArray();
|
||||
unsigned numContainedTypes = aDIArray.getNumElements();
|
||||
assert(i < numContainedTypes);
|
||||
EDIType tmpType((const DIType) aDIArray.getElement(i), norm);
|
||||
subType = tmpType;
|
||||
return subType;
|
||||
}
|
||||
|
||||
unsigned EDIType::getNumContainedTypes() const {
|
||||
if(isBasicType() || isVoidTy() || isEnumTy()) {
|
||||
return 0;
|
||||
}
|
||||
bool isArrayOrVectorTy = isArrayTy() || isVectorTy();
|
||||
if(isDerivedType() || isArrayOrVectorTy) {
|
||||
return 1;
|
||||
}
|
||||
DIArray aDIArray = getTypeArray();
|
||||
unsigned numContainedTypes = aDIArray.getNumElements();
|
||||
return numContainedTypes;
|
||||
}
|
||||
|
||||
const DIDerivedType& EDIType::getMember(unsigned i) const {
|
||||
static DIDerivedType aDIDerivedType;
|
||||
EDIType_assert(isUnionOrStructTy());
|
||||
DIArray aDIArray = getTypeArray();
|
||||
DIDescriptor aDIDescriptor = aDIArray.getElement(i);
|
||||
assert(aDIDescriptor.getTag() == dwarf::DW_TAG_member);
|
||||
aDIDerivedType = (DIDerivedType) aDIDescriptor;
|
||||
return aDIDerivedType;
|
||||
}
|
||||
|
||||
bool EDIType::isUnionOrStructTy(bool isStruct, bool isUnion) const {
|
||||
if(isOpaqueTy()) {
|
||||
return false;
|
||||
}
|
||||
if((isStruct && getTag() == dwarf::DW_TAG_structure_type) ||
|
||||
(isUnion && getTag() == dwarf::DW_TAG_union_type)) {
|
||||
EDIType_assert(isCompositeType());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EDIType::hasInnerPointers() const {
|
||||
if(isOpaqueTy() || isFunctionTy()) {
|
||||
return false;
|
||||
}
|
||||
if(isPointerTy()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
if(numContainedTypes == 0) {
|
||||
return false;
|
||||
}
|
||||
else if(isArrayTy() || isVectorTy()) {
|
||||
const EDIType subType = getContainedType(0);
|
||||
return subType.hasInnerPointers();
|
||||
}
|
||||
else {
|
||||
assert(isUnionOrStructTy());
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
const EDIType subType = getContainedType(i);
|
||||
if(subType.hasInnerPointers()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DIArray EDIType::getTypeArray() const {
|
||||
static std::set<std::string> nonOpaqueEmptyTypes;
|
||||
static std::set<std::string>::iterator nonOpaqueEmptyTypesIt;
|
||||
EDIType_assert(isCompositeType());
|
||||
DIArray aDIArray = ((const DICompositeType)aDIType).getTypeArray();
|
||||
if(aDIArray.getNumElements() == 0 && checkOpaqueTypes && myNames.size() > 0) {
|
||||
const EDIType *aType = NULL;
|
||||
std::string name;
|
||||
for(int i=myNames.size()-1;i>=0;i--) {
|
||||
name = myNames[i];
|
||||
aType = getStructEDITypeByName(name);
|
||||
if(aType) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(aType) {
|
||||
aDIArray = ((const DICompositeType *)aType->getDIType())->getTypeArray();
|
||||
nonOpaqueEmptyTypesIt = nonOpaqueEmptyTypes.find(name);
|
||||
if(nonOpaqueEmptyTypesIt == nonOpaqueEmptyTypes.end()) {
|
||||
EDITypeLog("Found a non-opaque composite type with 0 members! Name is: " << name);
|
||||
nonOpaqueEmptyTypes.insert(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return aDIArray;
|
||||
}
|
||||
|
||||
const EDIType* EDIType::getTopStructType(unsigned index) const {
|
||||
static unsigned level = 0;
|
||||
static unsigned structsLeft;
|
||||
static EDIType targetType;
|
||||
|
||||
if(level == 0) {
|
||||
structsLeft = index;
|
||||
}
|
||||
|
||||
if(isUnionOrStructTy() || isOpaqueTy()) {
|
||||
if(structsLeft == 0) {
|
||||
targetType = *this;
|
||||
return &targetType;
|
||||
}
|
||||
else {
|
||||
structsLeft--;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
const EDIType containedType(getContainedType(i));
|
||||
level++;
|
||||
const EDIType *topStructType = containedType.getTopStructType(index);
|
||||
level--;
|
||||
if(topStructType != NULL) {
|
||||
return topStructType;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other public methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void EDIType::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
void EDIType::printDescription(raw_ostream &OS, int skipUnions, int skipStructs, int allowMultiNames) const {
|
||||
static std::vector<const EDIType*> nestedTypes;
|
||||
int printMultiNames = allowMultiNames && myNames.size() > 1;
|
||||
if(allowMultiNames && !printMultiNames && isPointerTy() && myName.compare("")) {
|
||||
printMultiNames = 1;
|
||||
}
|
||||
|
||||
if(isOpaqueTy()) {
|
||||
OS << "opaque";
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
if(numContainedTypes == 0) {
|
||||
OS << (printMultiNames ? getNamesString() : getName());
|
||||
return;
|
||||
}
|
||||
|
||||
if(isPointerTy() && getContainedType(0).isUnionOrStructTy()) {
|
||||
bool isNestedType = false;
|
||||
unsigned j;
|
||||
for(j=0;j<nestedTypes.size();j++) {
|
||||
if(nestedTypes[j]->equals(this)) {
|
||||
isNestedType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isNestedType) {
|
||||
OS << "\\" << nestedTypes.size() - j;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nestedTypes.push_back(this);
|
||||
if(isPointerTy()) {
|
||||
const EDIType subType = getContainedType(0);
|
||||
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
|
||||
OS << "*";
|
||||
if(printMultiNames) {
|
||||
OS << "|" << getNamesString();
|
||||
}
|
||||
}
|
||||
else if(isArrayTy() || isVectorTy()) {
|
||||
const EDIType subType = getContainedType(0);
|
||||
unsigned numElements = getNumElements();
|
||||
char startSep = isArrayTy() ? '[' : '<';
|
||||
char endSep = isArrayTy() ? ']' : '>';
|
||||
OS << startSep;
|
||||
if(numElements) {
|
||||
OS << numElements << " x ";
|
||||
}
|
||||
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
|
||||
OS << endSep;
|
||||
}
|
||||
else if(isUnionOrStructTy()) {
|
||||
if(skipUnions && isUnionTy()) {
|
||||
OS << "(U) $" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
|
||||
nestedTypes.pop_back();
|
||||
return;
|
||||
}
|
||||
if(skipStructs && isStructTy()) {
|
||||
OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS"));
|
||||
nestedTypes.pop_back();
|
||||
return;
|
||||
}
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
OS << "{ ";
|
||||
if(isUnionTy()) {
|
||||
OS << "(U) ";
|
||||
}
|
||||
OS << "$" << (printMultiNames ? getNamesString() : (myName.compare("") ? myName : "ANONYMOUS")) << " ";
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if(i > 0) {
|
||||
OS << ", ";
|
||||
}
|
||||
EDIType subType = getContainedType(i);
|
||||
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
|
||||
}
|
||||
OS << " }";
|
||||
}
|
||||
else if(isFunctionTy()) {
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
assert(numContainedTypes > 0);
|
||||
EDIType subType = getContainedType(0);
|
||||
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
|
||||
numContainedTypes--;
|
||||
OS << " (";
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if(i > 0) {
|
||||
OS << ", ";
|
||||
}
|
||||
subType = getContainedType(i+1);
|
||||
subType.printDescription(OS, skipUnions, skipStructs, allowMultiNames);
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
else {
|
||||
OS << "???";
|
||||
}
|
||||
nestedTypes.pop_back();
|
||||
}
|
||||
|
||||
bool EDIType::equals(const EDIType *other) const {
|
||||
static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
|
||||
static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
|
||||
static int max_recursive_steps = -1;
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals>1) EDITypeErr("COMPARING :" << getTag() << ":" << getName() << " VS " << other->getTag() << ":" << other->getName());
|
||||
#endif
|
||||
if(isOpaqueTy() || other->isOpaqueTy()) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> ???1");
|
||||
#endif
|
||||
return isOpaqueTy() && other->isOpaqueTy();
|
||||
}
|
||||
if(getTag() != other->getTag()) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> false1");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
unsigned numOtherContainedTypes = other->getNumContainedTypes();
|
||||
if(numContainedTypes != numOtherContainedTypes) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> false2");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(getNumElements() != other->getNumElements()) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> false3");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(myName.compare(other->getName())) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> false4");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if((myNames.size() > 0 || other->getNames().size() > 0) && getNamesString().compare(other->getNamesString())) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> false5");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(numContainedTypes == 0) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> true1");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
MDNode *aNode = *(&aDIType);
|
||||
MDNode *otherNode = *(other->getDIType());
|
||||
if(aNode == otherNode) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> true2");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
int isUnionOrStruct = isUnionOrStructTy();
|
||||
int isNonAnonUnionOrStruct = isUnionOrStruct && myName.size() > 0;
|
||||
int saved_max_recursive_steps = max_recursive_steps;
|
||||
if(max_recursive_steps == -1 && isNonAnonUnionOrStruct) {
|
||||
//A simple way to break recursion for recursive non-anonymous structs/unions.
|
||||
max_recursive_steps = 10;
|
||||
}
|
||||
else if(max_recursive_steps == 0) {
|
||||
#if DEBUG_EDI_EQUALS
|
||||
if(debugEDIEquals) EDITypeErr("----> true4");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
max_recursive_steps--;
|
||||
}
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
const EDIType &subEDIType = getContainedType(i);
|
||||
const EDIType &subOtherEDIType = other->getContainedType(i);
|
||||
if(!subEDIType.equals(&subOtherEDIType)) {
|
||||
max_recursive_steps = saved_max_recursive_steps;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
max_recursive_steps = saved_max_recursive_steps;
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::string EDIType::lookupTypedefName(std::string &typedefName) {
|
||||
static std::string noName;
|
||||
for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
|
||||
E = DIFinder.type_end(); I != E; ++I) {
|
||||
DIType aDIType(*I);
|
||||
if(aDIType.getTag() == dwarf::DW_TAG_typedef && aDIType.getName().compare(typedefName)) {
|
||||
while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
|
||||
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
|
||||
}
|
||||
if(aDIType.getName().compare("")) {
|
||||
return aDIType.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
return noName;
|
||||
}
|
||||
|
||||
std::string EDIType::lookupUnionMemberName(TYPECONST Type* type) {
|
||||
std::string string;
|
||||
std::string error;
|
||||
if(!type->isStructTy() || type->getNumContainedTypes() != 1) {
|
||||
return "";
|
||||
}
|
||||
raw_string_ostream ostream(string);
|
||||
writeTypeSymbolic(ostream, type->getContainedType(0), EDIType::module);
|
||||
ostream.flush();
|
||||
Regex unionRegex("%(union|struct)\\.([^ ]+)", 0);
|
||||
assert(unionRegex.isValid(error));
|
||||
SmallVector<StringRef, 8> unionMatches;
|
||||
if(unionRegex.match(string, &unionMatches)) {
|
||||
return unionMatches[2];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const EDIType* EDIType::getStructEDITypeByName(std::string &typeName) {
|
||||
static EDIType aEDIType;
|
||||
assert(module);
|
||||
for (DebugInfoFinder::iterator I = DIFinder.type_begin(),
|
||||
E = DIFinder.type_end(); I != E; ++I) {
|
||||
const DIType aDIType(*I);
|
||||
//skip zero-element stuct types, necessary to avoid infinite recursion during opaque type lookup
|
||||
//xxx opaque type lookup should not be necessary but is there a bug in the frontend that leaves certain concrete types unnecessarily opaque?
|
||||
const EDIType tmpEDIType(aDIType, NORMALIZE, DO_NOT_CHECK_OPAQUE_TYPES);
|
||||
aEDIType = tmpEDIType;
|
||||
if(typeName.compare(aEDIType.getName())) {
|
||||
continue;
|
||||
}
|
||||
if(aEDIType.isUnionOrStructTy()) {
|
||||
return &aEDIType;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void EDIType::setModule(Module *M) {
|
||||
assert(module == NULL);
|
||||
module = M;
|
||||
DIFinder.processModule(*module);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Private methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
void EDIType::init(bool norm, bool checkOpaqueTypes) {
|
||||
EDIType_assert(isType());
|
||||
currentDimension = 0;
|
||||
this->checkOpaqueTypes = checkOpaqueTypes;
|
||||
myName = "";
|
||||
if(norm) {
|
||||
normalize();
|
||||
}
|
||||
if(myNames.size() == 0) {
|
||||
//nobody assigned names yet, do it here
|
||||
myName = isVoidTy() ? voidName : aDIType.getName();
|
||||
if(myName.compare("")) {
|
||||
myNames.push_back(myName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EDIType::normalize() {
|
||||
if(getTag() == dwarf::DW_TAG_typedef) {
|
||||
normalizeTypedef();
|
||||
}
|
||||
if(isBasicType() || isVoidTy() || isEnumTy() || isOpaqueTy()) {
|
||||
return;
|
||||
}
|
||||
if(isDerivedType()) {
|
||||
if(isPointerTy() || isUnionOrStructTy()) {
|
||||
return;
|
||||
}
|
||||
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
EDIType_assert(isCompositeType());
|
||||
if(isAggregateType() || isVectorTy() || isFunctionTy()) {
|
||||
return;
|
||||
}
|
||||
EDIType_assert(getNumContainedTypes() == 1);
|
||||
aDIType = *(getContainedType(0, DO_NOT_NORMALIZE).getDIType());
|
||||
normalize();
|
||||
}
|
||||
|
||||
void EDIType::normalizeTypedef() {
|
||||
myNames.clear();
|
||||
while(aDIType.getTag() == dwarf::DW_TAG_typedef) {
|
||||
if(aDIType.getName().compare("")) {
|
||||
myNames.push_back(aDIType.getName());
|
||||
}
|
||||
aDIType = PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType);
|
||||
}
|
||||
myName = isVoidTy() ? voidName : aDIType.getName();
|
||||
if(!myName.compare("")) {
|
||||
//anonymous typedefed type, use the deepest typedef name
|
||||
assert(!isBasicType());
|
||||
assert(myNames.size() > 0);
|
||||
myName = myNames[myNames.size()-1];
|
||||
}
|
||||
else {
|
||||
myNames.push_back(myName);
|
||||
}
|
||||
}
|
||||
|
||||
StringRef EDIType::voidName("void");
|
||||
Module *EDIType::module = NULL;
|
||||
DebugInfoFinder EDIType::DIFinder;
|
||||
|
||||
}
|
1137
minix/llvm/passes/magic/support/MagicUtil.cpp
Normal file
1137
minix/llvm/passes/magic/support/MagicUtil.cpp
Normal file
File diff suppressed because it is too large
Load diff
780
minix/llvm/passes/magic/support/SmartType.cpp
Normal file
780
minix/llvm/passes/magic/support/SmartType.cpp
Normal file
|
@ -0,0 +1,780 @@
|
|||
#include <magic/support/SmartType.h>
|
||||
#include <limits.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
#define DEBUG_EQUALS 0
|
||||
#define DEBUG_BFAS 0
|
||||
#define DEBUG_UNIONS 0
|
||||
int debugEquals = 0;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Constructors, destructor, and operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
SmartType::SmartType(const SmartType& et) {
|
||||
cloneFrom(et);
|
||||
}
|
||||
|
||||
SmartType::SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions, bool forceRawTypeRepresentation) {
|
||||
EDIType tmp(*aDIType);
|
||||
init(type, &tmp, useExceptions, forceRawTypeRepresentation);
|
||||
normalize();
|
||||
}
|
||||
|
||||
SmartType::SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
|
||||
init(type, aEDIType, useExceptions, forceRawTypeRepresentation);
|
||||
normalize();
|
||||
}
|
||||
|
||||
SmartType::~SmartType() {
|
||||
if(hasExplicitContainedEDITypes) {
|
||||
for(unsigned i=0;i<explicitContainedEDITypes.size();i++) {
|
||||
const EDIType* aEDIType = explicitContainedEDITypes[i];
|
||||
delete aEDIType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SmartType& SmartType::operator=(const SmartType& et) {
|
||||
if (this != &et) {
|
||||
cloneFrom(et);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SmartType::cloneFrom(const SmartType& et) {
|
||||
init(et.type, &et.aEDIType, et.useExceptions, false);
|
||||
if(et.hasExplicitContainedEDITypes) {
|
||||
hasExplicitContainedEDITypes = true;
|
||||
for(unsigned i=0;i<et.explicitContainedEDITypes.size();i++) {
|
||||
const EDIType* aEDIType = et.explicitContainedEDITypes[i];
|
||||
explicitContainedEDITypes.push_back(new EDIType(*aEDIType));
|
||||
}
|
||||
}
|
||||
isInconsistent = et.isInconsistent;
|
||||
rawTypeRepresentation = et.rawTypeRepresentation;
|
||||
bfas = et.bfas;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Getters
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const std::string SmartType::getDescription() const {
|
||||
return TypeUtil::getDescription(type, &aEDIType);
|
||||
}
|
||||
|
||||
const SmartType* SmartType::getContainedType(unsigned i) const {
|
||||
assert(!rawTypeRepresentation);
|
||||
bool hasBitFields = false;
|
||||
TYPECONST Type *subType = type->getContainedType(i);
|
||||
const SmartType* retSmartType = NULL;
|
||||
if(hasExplicitContainedEDITypes) {
|
||||
const EDIType subEDIType(*(explicitContainedEDITypes[i]));
|
||||
retSmartType = new SmartType(subType, &subEDIType, useExceptions);
|
||||
}
|
||||
else {
|
||||
if(aEDIType.isUnionTy()) {
|
||||
assert(i == 0);
|
||||
i = unionMemberIdx;
|
||||
}
|
||||
else if(bfas.size() > 0) {
|
||||
i = getBFAFreeIdx(i, bfas);
|
||||
hasBitFields = true;
|
||||
}
|
||||
const EDIType subEDIType(aEDIType.getContainedType(i));
|
||||
retSmartType = new SmartType(subType, &subEDIType, useExceptions, hasBitFields && subEDIType.isIntegerTy() && subType->isArrayTy());
|
||||
}
|
||||
return retSmartType;
|
||||
}
|
||||
|
||||
unsigned SmartType::getNumContainedTypes() const {
|
||||
if(rawTypeRepresentation || aEDIType.isComplexFloatingPointTy() || isOpaqueTy()) {
|
||||
return 0;
|
||||
}
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
unsigned numContainedEDITypes;
|
||||
if(hasExplicitContainedEDITypes) {
|
||||
numContainedEDITypes = explicitContainedEDITypes.size();
|
||||
}
|
||||
else {
|
||||
if(aEDIType.isUnionTy()) {
|
||||
numContainedEDITypes = 1;
|
||||
}
|
||||
else {
|
||||
numContainedEDITypes = aEDIType.getNumContainedTypes();
|
||||
if(bfas.size() > 0) {
|
||||
for(unsigned i=0;i<bfas.size();i++) {
|
||||
numContainedEDITypes -= (bfas[i].getSize() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(numContainedTypes == numContainedEDITypes+1 && isPaddedTy()) {
|
||||
numContainedTypes--;
|
||||
}
|
||||
if(numContainedTypes != numContainedEDITypes) {
|
||||
if(isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
|
||||
numContainedTypes = 1;
|
||||
}
|
||||
}
|
||||
SmartType_assert(numContainedTypes == numContainedEDITypes);
|
||||
return numContainedTypes;
|
||||
}
|
||||
|
||||
const DIDerivedType& SmartType::getMember(unsigned i) const {
|
||||
assert(!rawTypeRepresentation);
|
||||
if(bfas.size() > 0) {
|
||||
i = getBFAFreeIdx(i, bfas);
|
||||
}
|
||||
return aEDIType.getMember(i);
|
||||
}
|
||||
|
||||
unsigned SmartType::getUnionMemberIdx() const {
|
||||
assert(!rawTypeRepresentation);
|
||||
SmartType_assert(isTy(type->isStructTy(), aEDIType.isUnionTy(), "getUnionMemberIdx"));
|
||||
SmartType_assert(getNumContainedTypes() == 1);
|
||||
TYPECONST Type* uMemberType = type->getContainedType(0);
|
||||
unsigned numSubEDITypes = aEDIType.getNumContainedTypes();
|
||||
std::vector<unsigned> indexes;
|
||||
int maxWeakConsistencyLevel = -1;
|
||||
unsigned maxWeakConsistencyIndex = -1;
|
||||
int maxWeakConsistencyLevelEntries;
|
||||
unsigned index;
|
||||
for(unsigned i=0;i<numSubEDITypes;i++) {
|
||||
int weakConsistencyLevel;
|
||||
EDIType subEDIType = aEDIType.getContainedType(i);
|
||||
if(isTypeConsistent(uMemberType, &subEDIType, true, &weakConsistencyLevel)) {
|
||||
indexes.push_back(i);
|
||||
if(weakConsistencyLevel > maxWeakConsistencyLevel) {
|
||||
maxWeakConsistencyLevel = weakConsistencyLevel;
|
||||
maxWeakConsistencyIndex = i;
|
||||
maxWeakConsistencyLevelEntries = 1;
|
||||
}
|
||||
else if(weakConsistencyLevel == maxWeakConsistencyLevel) {
|
||||
maxWeakConsistencyLevelEntries++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(indexes.size() == 0) {
|
||||
//try to match names if we failed before
|
||||
std::string name = EDIType::lookupUnionMemberName(type);
|
||||
if(name.compare("")) {
|
||||
for(unsigned i=0;i<numSubEDITypes;i++) {
|
||||
EDIType subEDIType = aEDIType.getContainedType(i);
|
||||
if(!subEDIType.getName().compare(name)) {
|
||||
indexes.push_back(i);
|
||||
maxWeakConsistencyIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(indexes.size() == 0) {
|
||||
//No valid union member found
|
||||
#if DEBUG_UNIONS
|
||||
SmartTypeErr("getUnionMemberIdx: resorting to a raw type. No valid union member found for: " << getDescription());
|
||||
#endif
|
||||
return UINT_MAX;
|
||||
}
|
||||
index = maxWeakConsistencyIndex;
|
||||
if(indexes.size() > 1) {
|
||||
SmartTypeLog("getUnionMemberIdx: warning: multiple valid union members found, automatically selecting the first most-consistent member:");
|
||||
SmartTypeLog(" - target member type is: " << TypeUtil::getDescription(uMemberType));
|
||||
SmartTypeLog(" - selected index is: " << index);
|
||||
for(unsigned i=0;i<indexes.size();i++) {
|
||||
EDIType subEDIType = aEDIType.getContainedType(indexes[i]);
|
||||
SmartTypeLog(" - " << indexes[i] << ". " << TypeUtil::getDescription(&subEDIType));
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
const SmartType* SmartType::getTopStructType(unsigned index) const {
|
||||
TYPECONST Type *topType = TypeUtil::lookupTopStructType(type, index);
|
||||
const EDIType *topEDIType = aEDIType.getTopStructType(index);
|
||||
assert((topType && topEDIType) || (!topType && !topEDIType));
|
||||
if(topType) {
|
||||
const SmartType* retSmartType = new SmartType(topType, topEDIType);
|
||||
return retSmartType;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other public methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void SmartType::verify() const {
|
||||
SmartType_assert(isTypeConsistent());
|
||||
}
|
||||
|
||||
void SmartType::print(raw_ostream &OS) const {
|
||||
OS << getDescription();
|
||||
}
|
||||
|
||||
bool SmartType::equals(const SmartType* other, bool isDebug) const {
|
||||
static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
|
||||
static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("COMPARING :" << getDescription() << " VS " << other->getDescription());
|
||||
#endif
|
||||
if(type != other->getType()) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false1");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(isOpaqueTy() || other->isOpaqueTy()) {
|
||||
return isOpaqueTy() && other->isOpaqueTy();
|
||||
}
|
||||
if(aEDIType.getTag() != other->getEDIType()->getTag()) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false1b");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(isFunctionTy() && (!isTypeConsistent() || !other->isTypeConsistent())) {
|
||||
//we just compare the types for inconsistent functions types
|
||||
return true;
|
||||
}
|
||||
if(hasRawTypeRepresentation() || other->hasRawTypeRepresentation()) {
|
||||
return !aEDIType.getNamesString().compare(other->getEDIType()->getNamesString());
|
||||
}
|
||||
unsigned numContainedTypes = getNumContainedTypes();
|
||||
unsigned otherNumContainedTypes = other->getNumContainedTypes();
|
||||
if(numContainedTypes != otherNumContainedTypes) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false2");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
unsigned numElements = aEDIType.getNumElements();
|
||||
unsigned otherNumElements = other->getEDIType()->getNumElements();
|
||||
if(numElements != otherNumElements) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false2b");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
std::string name = aEDIType.getName();
|
||||
std::string otherName = other->getEDIType()->getName();
|
||||
if(name.compare(otherName)) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false3: " << name << " vs " << otherName);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(aEDIType.getNames().size() > 1 || other->getEDIType()->getNames().size() > 1) {
|
||||
std::string namesString = aEDIType.getNamesString();
|
||||
std::string otherNamesString = other->getEDIType()->getNamesString();
|
||||
if(namesString.compare(otherNamesString)) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false4: " << namesString << " vs " << otherNamesString);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(numContainedTypes == 0) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> true4");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
MDNode *node = *(aEDIType.getDIType());
|
||||
MDNode *otherNode = *(other->getEDIType()->getDIType());
|
||||
if(node == otherNode) {
|
||||
return true;
|
||||
}
|
||||
for(unsigned i=0;i<SmartType::equalsNestedTypes.size();i++) {
|
||||
if(type == SmartType::equalsNestedTypes[i]) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> true5");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//before digging the type tree, see if we have these 2 metadata nodes in cache
|
||||
//this gives us an impressive speedup
|
||||
MDNode *minNode = node < otherNode ? node : otherNode;
|
||||
MDNode *maxNode = node < otherNode ? otherNode : node;
|
||||
compatibleMDNodesIt = compatibleMDNodes.find(std::pair<MDNode*, MDNode*>(minNode, maxNode));
|
||||
if(compatibleMDNodesIt != compatibleMDNodes.end()) {
|
||||
return true;
|
||||
}
|
||||
SmartType::equalsNestedTypes.push_back(type);
|
||||
const SmartType* containedType = NULL;
|
||||
const SmartType* otherContainedType = NULL;
|
||||
bool sameContainedTypes = true;
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
containedType = getContainedType(i);
|
||||
otherContainedType = other->getContainedType(i);
|
||||
sameContainedTypes = containedType->equals(otherContainedType);
|
||||
delete containedType;
|
||||
delete otherContainedType;
|
||||
if(!sameContainedTypes) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SmartType::equalsNestedTypes.pop_back();
|
||||
if(!sameContainedTypes) {
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> false6");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#if DEBUG_EQUALS
|
||||
if(debugEquals) SmartTypeErr("----> true7");
|
||||
#endif
|
||||
compatibleMDNodes.insert(std::pair<MDNode*, MDNode*>(minNode, maxNode));
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
const SmartType* SmartType::getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG) {
|
||||
//ignore anonymous strings
|
||||
if(GV->getName().startswith(".str")) {
|
||||
return NULL;
|
||||
}
|
||||
Value *DIGV = Backports::findDbgGlobalDeclare(GV);
|
||||
if (!DIGV) {
|
||||
return NULL;
|
||||
}
|
||||
DIGlobalVariable Var(cast<MDNode>(DIGV));
|
||||
DIType aDIType = Var.getType();
|
||||
const SmartType* retSmartType = new SmartType(GV->getType()->getElementType(), &aDIType);
|
||||
if(DIG) {
|
||||
*DIG = Var;
|
||||
}
|
||||
return retSmartType;
|
||||
}
|
||||
|
||||
const SmartType* SmartType::getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV) {
|
||||
const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(AI);
|
||||
if (!DDI) {
|
||||
return NULL;
|
||||
}
|
||||
if(DDI == (const DbgDeclareInst *) -1) {
|
||||
return (const SmartType*)-1;
|
||||
}
|
||||
DIVariable Var(cast<MDNode>(DDI->getVariable()));
|
||||
DIType aDIType = Var.getType();
|
||||
if(DIV) {
|
||||
*DIV = Var;
|
||||
}
|
||||
const SmartType* aSmartType = new SmartType(AI->getAllocatedType(), &aDIType);
|
||||
return aSmartType;
|
||||
}
|
||||
|
||||
const SmartType* SmartType::getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS) {
|
||||
Value *DIF = Backports::findDbgSubprogramDeclare(F);
|
||||
if (!DIF) {
|
||||
return NULL;
|
||||
}
|
||||
DISubprogram Sub(cast<MDNode>(DIF));
|
||||
DIType aDIType = Sub.getType();
|
||||
const SmartType* retSmartType = new SmartType(F->getType()->getElementType(), &aDIType);
|
||||
if(DIS) {
|
||||
*DIS = Sub;
|
||||
}
|
||||
return retSmartType;
|
||||
}
|
||||
|
||||
const SmartType* SmartType::getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion) {
|
||||
std::string structName((isUnion ? "union." : "struct.") + name);
|
||||
|
||||
TYPECONST Type *targetType = M.getTypeByName(structName);
|
||||
const EDIType *targetEDIType = EDIType::getStructEDITypeByName(name);
|
||||
|
||||
const SmartType *retSmartType = NULL;
|
||||
if(targetType && targetEDIType) {
|
||||
retSmartType = new SmartType(targetType, targetEDIType);
|
||||
}
|
||||
return retSmartType;
|
||||
}
|
||||
|
||||
std::vector<const SmartType*>* SmartType::getTopStructSmartTypes(Module &M, GlobalVariable* GV) {
|
||||
std::vector<std::string> names;
|
||||
std::vector<unsigned> flags;
|
||||
TypeUtil::parseTopStructTypes(M, GV->getType()->getElementType(), &names, &flags);
|
||||
std::vector<const SmartType*> *vector = new std::vector<const SmartType*>;
|
||||
for(unsigned i=0;i<names.size();i++) {
|
||||
std::string entryName = names[i];
|
||||
unsigned entryFlags = flags[i];
|
||||
const SmartType *aSmartType = NULL;
|
||||
if(!(entryFlags & TypeUtil::TYPE_ANONYMOUS) && !(entryFlags & TypeUtil::TYPE_UNNAMED)) {
|
||||
aSmartType = getStructSmartTypeByName(M, GV, entryName, (entryFlags & TypeUtil::TYPE_UNION));
|
||||
}
|
||||
if(aSmartType == NULL) {
|
||||
//this method can fail due to name clashing but is the only one possible for anonymous or unnamed struct types
|
||||
const SmartType *GVSmartType = getSmartTypeFromGV(M, GV);
|
||||
assert(GVSmartType && "Unable to find a match for anonymous or unnamed struct type");
|
||||
aSmartType = GVSmartType->getTopStructType(i);
|
||||
delete GVSmartType;
|
||||
assert(aSmartType != NULL);
|
||||
}
|
||||
vector->push_back(aSmartType);
|
||||
}
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Private methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void SmartType::init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
|
||||
this->type = type;
|
||||
this->aEDIType = *aEDIType;
|
||||
this->useExceptions = useExceptions;
|
||||
hasExplicitContainedEDITypes = false;
|
||||
isInconsistent = false;
|
||||
rawTypeRepresentation = false;
|
||||
unionMemberIdx = 0;
|
||||
if(aEDIType->isUnionTy()) {
|
||||
if(forceRawUnions) {
|
||||
rawTypeRepresentation = true;
|
||||
}
|
||||
else {
|
||||
unionMemberIdx = getUnionMemberIdx();
|
||||
if(unionMemberIdx == UINT_MAX) {
|
||||
rawTypeRepresentation = true;
|
||||
unionMemberIdx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(forceRawTypeRepresentation || (forceRawBitfields && BitFieldAggregation::hasBitFields(type, &(this->aEDIType)))) {
|
||||
rawTypeRepresentation = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SmartType::normalize() {
|
||||
if(isFunctionTy() && !hasExplicitContainedEDITypes) {
|
||||
flattenFunctionTy();
|
||||
hasExplicitContainedEDITypes = true;
|
||||
}
|
||||
if(!hasExplicitContainedEDITypes && !rawTypeRepresentation) {
|
||||
if(!BitFieldAggregation::getBitFieldAggregations(type, &aEDIType, bfas, true)) {
|
||||
//failed to determine bfas
|
||||
#if DEBUG_BFAS
|
||||
SmartTypeErr("normalize: resorting to a raw type. Cannot determine bfas for: " << getDescription());
|
||||
#endif
|
||||
rawTypeRepresentation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SmartType::flattenFunctionTy() {
|
||||
SmartType_assert(isFunctionTy() && !hasExplicitContainedEDITypes);
|
||||
SmartType_assert(explicitContainedEDITypes.size() == 0);
|
||||
#if MAGIC_FLATTEN_FUNCTION_ARGS
|
||||
int ret = flattenFunctionArgs(type, &aEDIType, 0);
|
||||
if(ret < 0 || explicitContainedEDITypes.size() != type->getNumContainedTypes()) {
|
||||
SmartTypeLog("Warning: function flattening produced an inconsistent type!");
|
||||
isInconsistent = true;
|
||||
}
|
||||
#else
|
||||
isInconsistent = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int SmartType::flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType) {
|
||||
unsigned containedTypes = type->getNumContainedTypes();
|
||||
unsigned containedEDITypes = aEDIType->isUnionTy() ? 1 : aEDIType->getNumContainedTypes();
|
||||
unsigned containedEDIOptions = aEDIType->isUnionTy() ? aEDIType->getNumContainedTypes() : 1;
|
||||
int ret;
|
||||
|
||||
unsigned nextContainedEDIType = 0;
|
||||
while(nextContainedEDIType < containedEDITypes) {
|
||||
SmartType_assert(nextContainedType < containedTypes);
|
||||
TYPECONST Type *containedType = type->getContainedType(nextContainedType);
|
||||
unsigned currExplicitEDITypes = explicitContainedEDITypes.size();
|
||||
unsigned i;
|
||||
for(i=nextContainedEDIType;i<nextContainedEDIType+containedEDIOptions;i++) {
|
||||
const EDIType containedEDIType = aEDIType->getContainedType(i);
|
||||
if(isTypeConsistent(containedType, &containedEDIType)) {
|
||||
explicitContainedEDITypes.push_back(new EDIType(containedEDIType));
|
||||
break;
|
||||
}
|
||||
if(!containedEDIType.isAggregateType()) {
|
||||
continue;
|
||||
}
|
||||
ret = flattenFunctionArgs(type, &containedEDIType, nextContainedType);
|
||||
if(ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i >= nextContainedEDIType+containedEDIOptions) {
|
||||
while(explicitContainedEDITypes.size() > currExplicitEDITypes) {
|
||||
EDIType* aEDIType = explicitContainedEDITypes[explicitContainedEDITypes.size()-1];
|
||||
explicitContainedEDITypes.pop_back();
|
||||
delete aEDIType;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
nextContainedType += (explicitContainedEDITypes.size() - currExplicitEDITypes);
|
||||
nextContainedEDIType++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SmartType::isTy(bool isTyType, bool isTyEDIType, const char* source) const {
|
||||
bool check = (isTyType && isTyEDIType) || (!isTyType && !isTyEDIType);
|
||||
if(!check) {
|
||||
SmartTypeErr(source << " failed");
|
||||
}
|
||||
SmartType_assert(check);
|
||||
return isTyType;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Private static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
unsigned SmartType::getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas) {
|
||||
for(unsigned j=0;j<inputBfas.size();j++) {
|
||||
if(i<inputBfas[j].getEDITypeIndex()) {
|
||||
break;
|
||||
}
|
||||
else if(i>inputBfas[j].getEDITypeIndex()) {
|
||||
i += (inputBfas[j].getSize() - 1);
|
||||
}
|
||||
else {
|
||||
i = inputBfas[j].getRepresentativeEDITypeIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
bool SmartType::isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType) {
|
||||
if(aEDIType->isVoidTy()) {
|
||||
return type->isVoidTy() || (type->isIntegerTy() && ((IntegerType*)type)->getBitWidth() == 8);
|
||||
}
|
||||
if(type->isFloatingPointTy()) {
|
||||
return aEDIType->isFloatingPointTy();
|
||||
}
|
||||
if(type->isIntegerTy()) {
|
||||
if(aEDIType->isCharTy() || aEDIType->isBoolTy()) {
|
||||
return (((IntegerType*)type)->getBitWidth() <= 8);
|
||||
}
|
||||
return aEDIType->isIntegerTy() || aEDIType->isEnumTy();
|
||||
}
|
||||
if(type->isFunctionTy()) {
|
||||
return aEDIType->isFunctionTy();
|
||||
}
|
||||
if(TypeUtil::isOpaqueTy(type)) {
|
||||
return (aEDIType->isOpaqueTy());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SmartType::isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType) {
|
||||
assert(aSmartType->isUseExceptions());
|
||||
TYPECONST Type *type = aSmartType->getType();
|
||||
const EDIType *aEDIType = aSmartType->getEDIType();
|
||||
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
|
||||
for(unsigned j=0;j<nestedTypes.size();j++) {
|
||||
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned nTypes = type->getNumContainedTypes();
|
||||
unsigned nEDITypes = aEDIType->getNumContainedTypes();
|
||||
if(nTypes == 0 || nEDITypes == 0) {
|
||||
if(nTypes != 0 || nEDITypes != 0) {
|
||||
return false;
|
||||
}
|
||||
return isRawTypeConsistent(type, aEDIType);
|
||||
}
|
||||
if(!aSmartType->verifyTy()) {
|
||||
return false;
|
||||
}
|
||||
unsigned numContainedTypes = aSmartType->getNumContainedTypes();
|
||||
nestedTypes.push_back(type);
|
||||
nestedEDITypes.push_back(aEDIType);
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
const SmartType *containedSmartType = aSmartType->getContainedType(i);
|
||||
assert(containedSmartType->isUseExceptions());
|
||||
SmartType clonedSmartType(*containedSmartType);
|
||||
assert(clonedSmartType.isUseExceptions());
|
||||
delete containedSmartType;
|
||||
if(!isTypeConsistent2(nestedTypes, nestedEDITypes, &clonedSmartType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SmartType::isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType) {
|
||||
/* Exception-handling based isTypeConsistent(). Broken with -fno-exceptions. */
|
||||
static std::vector<TYPECONST Type*> nestedTypes;
|
||||
static std::vector<const EDIType*> nestedEDITypes;
|
||||
static unsigned level = 0;
|
||||
|
||||
if(level == 0) {
|
||||
nestedTypes.clear();
|
||||
nestedEDITypes.clear();
|
||||
}
|
||||
|
||||
bool checkTypeConsistent = false;
|
||||
bool useExceptions = true;
|
||||
level++;
|
||||
assert(useExceptions);
|
||||
TRY(
|
||||
const SmartType aSmartType(type, aEDIType, useExceptions);
|
||||
checkTypeConsistent = isTypeConsistent2(nestedTypes, nestedEDITypes, &aSmartType);
|
||||
)
|
||||
CATCH(std::exception& e,
|
||||
checkTypeConsistent = false;
|
||||
)
|
||||
level--;
|
||||
return checkTypeConsistent;
|
||||
}
|
||||
|
||||
bool SmartType::isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas, int *weakConsistencyLevel) {
|
||||
static std::vector<TYPECONST Type*> nestedTypes;
|
||||
static std::vector<const EDIType*> nestedEDITypes;
|
||||
static unsigned level = 0;
|
||||
|
||||
if(level == 0) {
|
||||
if(weakConsistencyLevel) {
|
||||
*weakConsistencyLevel = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
|
||||
for(unsigned j=0;j<nestedTypes.size();j++) {
|
||||
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned nTypes = type->getNumContainedTypes();
|
||||
unsigned nEDITypes = aEDIType->getNumContainedTypes();
|
||||
if(nTypes == 0 || nEDITypes == 0) {
|
||||
if(nTypes != 0 || nEDITypes != 0) {
|
||||
return false;
|
||||
}
|
||||
return isRawTypeConsistent(type, aEDIType);
|
||||
}
|
||||
|
||||
if(aEDIType->isOpaqueTy()) {
|
||||
return (TypeUtil::isOpaqueTy(type));
|
||||
}
|
||||
|
||||
bool isArrayOrVectorTy = aEDIType->isArrayTy() || aEDIType->isVectorTy();
|
||||
unsigned nEDINumElements = aEDIType->getNumElements();
|
||||
if(aEDIType->isDerivedType() || isArrayOrVectorTy) {
|
||||
TYPECONST Type *nextType = type;
|
||||
if(aEDIType->isPointerTy()) {
|
||||
if(!type->isPointerTy()) {
|
||||
return false;
|
||||
}
|
||||
nextType = type->getContainedType(0);
|
||||
}
|
||||
else if(aEDIType->isArrayTy()) {
|
||||
if(!type->isArrayTy() || ((ArrayType*)type)->getNumElements() != nEDINumElements) {
|
||||
return false;
|
||||
}
|
||||
nextType = type->getContainedType(0);
|
||||
}
|
||||
else if(aEDIType->isVectorTy()) {
|
||||
if(!type->isVectorTy() || ((VectorType*)type)->getNumElements() != nEDINumElements) {
|
||||
return false;
|
||||
}
|
||||
nextType = type->getContainedType(0);
|
||||
}
|
||||
const EDIType aEDISubType(aEDIType->getContainedType(0));
|
||||
nestedEDITypes.push_back(aEDIType);
|
||||
nestedTypes.push_back(type);
|
||||
level++;
|
||||
bool ret = isTypeConsistent(nextType, &aEDISubType, useBfas, weakConsistencyLevel);
|
||||
level--;
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return ret;
|
||||
}
|
||||
else if(aEDIType->isCompositeType()) {
|
||||
if(!aEDIType->isUnionOrStructTy() && !aEDIType->isVectorTy() && !aEDIType->isFunctionTy()) {
|
||||
return false;
|
||||
}
|
||||
if(aEDIType->isUnionOrStructTy() && !type->isStructTy()) {
|
||||
return false;
|
||||
}
|
||||
if(aEDIType->isVectorTy() && !type->isVectorTy()) {
|
||||
return false;
|
||||
}
|
||||
if(aEDIType->isFunctionTy() && !type->isFunctionTy()) {
|
||||
return false;
|
||||
}
|
||||
if(aEDIType->isUnionTy() || aEDIType->isFunctionTy()) {
|
||||
if(weakConsistencyLevel) {
|
||||
*weakConsistencyLevel = level;
|
||||
}
|
||||
return true; //xxx we should be less conservative here
|
||||
}
|
||||
unsigned numContainedEDITypes = aEDIType->getNumContainedTypes();
|
||||
std::vector<BitFieldAggregation> myBfas;
|
||||
if(numContainedEDITypes != type->getNumContainedTypes()) {
|
||||
if(!useBfas) {
|
||||
return false;
|
||||
}
|
||||
if(!BitFieldAggregation::getBitFieldAggregations(type, aEDIType, myBfas, true)) {
|
||||
return false;
|
||||
}
|
||||
for(unsigned i=0;i<myBfas.size();i++) {
|
||||
numContainedEDITypes -= (myBfas[i].getSize() - 1);
|
||||
}
|
||||
if(numContainedEDITypes != type->getNumContainedTypes()) {
|
||||
return false;
|
||||
}
|
||||
nestedEDITypes.push_back(aEDIType);
|
||||
nestedTypes.push_back(type);
|
||||
level++;
|
||||
for(unsigned i=0;i<numContainedEDITypes;i++) {
|
||||
const EDIType aEDISubType(aEDIType->getContainedType(getBFAFreeIdx(i, myBfas)));
|
||||
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
|
||||
level--;
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
level--;
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return true;
|
||||
}
|
||||
nestedEDITypes.push_back(aEDIType);
|
||||
nestedTypes.push_back(type);
|
||||
level++;
|
||||
for(unsigned i=0;i<numContainedEDITypes;i++) {
|
||||
const EDIType aEDISubType(aEDIType->getContainedType(i));
|
||||
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
|
||||
level--;
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
level--;
|
||||
nestedTypes.pop_back();
|
||||
nestedEDITypes.pop_back();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<TYPECONST Type*> SmartType::equalsNestedTypes;
|
||||
|
||||
}
|
388
minix/llvm/passes/magic/support/TypeUtil.cpp
Normal file
388
minix/llvm/passes/magic/support/TypeUtil.cpp
Normal file
|
@ -0,0 +1,388 @@
|
|||
#include <magic/support/TypeUtil.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public static methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool TypeUtil::isPaddedType(TYPECONST Type *type) {
|
||||
if(type->getNumContainedTypes() < 2) {
|
||||
return false;
|
||||
}
|
||||
TYPECONST Type *lastContainedType = type->getContainedType(type->getNumContainedTypes() - 1);
|
||||
bool paddedTy = lastContainedType->isIntegerTy() || (lastContainedType->isArrayTy() &&
|
||||
lastContainedType->getContainedType(0)->isIntegerTy());
|
||||
return paddedTy;
|
||||
}
|
||||
|
||||
TYPECONST Type* TypeUtil::lookupTopStructType(TYPECONST Type *type, unsigned index) {
|
||||
static unsigned level = 0;
|
||||
static unsigned structsLeft;
|
||||
|
||||
if(level == 0) {
|
||||
structsLeft = index;
|
||||
}
|
||||
|
||||
if(type->isStructTy() || TypeUtil::isOpaqueTy(type)) {
|
||||
if(structsLeft == 0) {
|
||||
return type;
|
||||
}
|
||||
else {
|
||||
structsLeft--;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
TYPECONST Type *containedType = type->getContainedType(i);
|
||||
level++;
|
||||
TYPECONST Type *topStructType = lookupTopStructType(containedType, index);
|
||||
level--;
|
||||
if(topStructType != NULL) {
|
||||
return topStructType;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TypeUtil::parseTopStructTypes(Module &M, TYPECONST Type *type, std::vector<std::string> *names, std::vector<unsigned> *flags) {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
EDIType::writeTypeSymbolic(ostream, type, &M);
|
||||
ostream.flush();
|
||||
Regex anonRegex("%(union|struct)\\.(\\.*[0-9]*anon)", 0);
|
||||
Regex regularRegex("%(union|struct)\\.([^{}(), *]+)", 0);
|
||||
Regex unnamedRegex("%(%)?([0-9]+)", 0);
|
||||
std::string error;
|
||||
assert(anonRegex.isValid(error) && regularRegex.isValid(error) && unnamedRegex.isValid(error));
|
||||
size_t index = -1;
|
||||
while((index=string.find("%", index+1))!=std::string::npos) {
|
||||
std::string entryString = string.substr(index);
|
||||
if(entryString[entryString.size()-1] == ']') {
|
||||
entryString = entryString.substr(0, entryString.size()-1);
|
||||
}
|
||||
StringRef entryStringRef(entryString);
|
||||
SmallVector<StringRef, 8> entryMatches;
|
||||
unsigned entryFlags;
|
||||
entryMatches.clear();
|
||||
entryFlags = 0;
|
||||
if(anonRegex.match(entryString, &entryMatches)) {
|
||||
entryFlags |= TypeUtil::TYPE_ANONYMOUS;
|
||||
}
|
||||
else if(unnamedRegex.match(entryString, &entryMatches)) {
|
||||
entryFlags |= TypeUtil::TYPE_UNNAMED;
|
||||
}
|
||||
else {
|
||||
assert(regularRegex.match(entryString, &entryMatches) && "Unsupported struct type");
|
||||
}
|
||||
assert(entryStringRef.startswith(entryMatches[0]));
|
||||
std::string prefix = entryMatches[1];
|
||||
std::string name = entryMatches[2];
|
||||
entryFlags |= !prefix.compare("union") ? TypeUtil::TYPE_UNION : TypeUtil::TYPE_STRUCT;
|
||||
if(names) names->push_back(name);
|
||||
if(flags) flags->push_back(entryFlags);
|
||||
}
|
||||
}
|
||||
|
||||
int TypeUtil::findTopStructTypeIndex(Module &M, TYPECONST Type *type, std::string &name, unsigned flagsToAccept) {
|
||||
std::vector<std::string> names;
|
||||
std::vector<unsigned> flags;
|
||||
parseTopStructTypes(M, type, &names, &flags);
|
||||
int index = -1;
|
||||
for(unsigned i=0;i<names.size();i++) {
|
||||
if(!name.compare(names[i]) && (flagsToAccept | flags[i]) == flagsToAccept) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
TYPECONST Type* TypeUtil::getRecursiveElementType(TYPECONST Type *type) {
|
||||
TYPECONST PointerType* pointerType = dyn_cast<PointerType>(type);
|
||||
if(!pointerType) {
|
||||
return type;
|
||||
}
|
||||
return getRecursiveElementType(pointerType->getElementType());
|
||||
}
|
||||
|
||||
TYPECONST Type* TypeUtil::getArrayFreePointerType(TYPECONST Type *type) {
|
||||
if(type->isPointerTy() || type->isArrayTy()) {
|
||||
TYPECONST Type* elementType = getArrayFreePointerType(type->getContainedType(0));
|
||||
type = PointerType::get(elementType, 0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
bool TypeUtil::hasInnerPointers(TYPECONST Type *type) {
|
||||
if(TypeUtil::isOpaqueTy(type) || type->isFunctionTy()) {
|
||||
return false;
|
||||
}
|
||||
if(type->isPointerTy()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
if(numContainedTypes == 0) {
|
||||
return false;
|
||||
}
|
||||
else if(type->isArrayTy() || type->isVectorTy()) {
|
||||
return hasInnerPointers(type->getContainedType(0));
|
||||
}
|
||||
else {
|
||||
assert(type->isStructTy());
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if(hasInnerPointers(type->getContainedType(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeUtil::isArrayAsStructTy(TYPECONST Type *type) {
|
||||
if(!type->isStructTy()) {
|
||||
return false;
|
||||
}
|
||||
return type->getNumContainedTypes() == 1 || type->getContainedType(0) == type->getContainedType(1);
|
||||
}
|
||||
|
||||
unsigned TypeUtil::getHash(TYPECONST Type* type) {
|
||||
return (unsigned) PassUtil::getTypeHash(type);
|
||||
}
|
||||
|
||||
const std::string TypeUtil::getDescription(TYPECONST Type* type,
|
||||
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
|
||||
std::string string;
|
||||
if(!PRINT_SKIP_UNIONS && !PRINT_SKIP_STRUCTS && PRINT_USE_BUILTIN_PRINTING) {
|
||||
string = PassUtil::getTypeDescription(type);
|
||||
}
|
||||
else {
|
||||
raw_string_ostream ostream(string);
|
||||
printTypeString(ostream, type, max_chars, max_levels);
|
||||
ostream.flush();
|
||||
}
|
||||
if(VERBOSE_LEVEL > 0) {
|
||||
string = getFormattedDescription(string);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
const std::string TypeUtil::getDescription(const EDIType* aEDIType) {
|
||||
std::string string;
|
||||
string = aEDIType->getDescription(PRINT_SKIP_UNIONS, PRINT_SKIP_STRUCTS, PRINT_MULTI_NAMES);
|
||||
if(VERBOSE_LEVEL > 0) {
|
||||
string = getFormattedDescription(string);
|
||||
}
|
||||
if(VERBOSE_LEVEL > 1) {
|
||||
raw_string_ostream ostream(string);
|
||||
ostream << "\n\t";
|
||||
aEDIType->getDIType()->print(ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
const std::string TypeUtil::getDescription(TYPECONST Type* type, const EDIType* aEDIType,
|
||||
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
|
||||
std::string string;
|
||||
string = "[\ntype = \n";
|
||||
string.append(TypeUtil::getDescription(type, max_chars, max_levels));
|
||||
string.append("\nEDIType =\n");
|
||||
string.append(TypeUtil::getDescription(aEDIType));
|
||||
string.append("\n]");
|
||||
return string;
|
||||
}
|
||||
|
||||
const std::string TypeUtil::getFormattedDescription(std::string &description) {
|
||||
std::string string;
|
||||
raw_string_ostream ostream(string);
|
||||
printFormattedTypeString(ostream, description, 0, description.size());
|
||||
ostream.flush();
|
||||
return string;
|
||||
}
|
||||
|
||||
void TypeUtil::printFormattedTypeString(raw_ostream &OS, std::string &typeStr, int start, int length) {
|
||||
static int indent = 0;
|
||||
for(int k=0;k<indent;k++) OS << " ";
|
||||
for(int i=start;i<start+length;i++) {
|
||||
OS << typeStr[i];
|
||||
if(typeStr[i] == '{') {
|
||||
int newLength = 0;
|
||||
int structsFound = 0;
|
||||
int j;
|
||||
for(j=i+2;j<start+length;j++) {
|
||||
switch(typeStr[j]) {
|
||||
case '{':
|
||||
structsFound++;
|
||||
break;
|
||||
case '}':
|
||||
if(structsFound == 0) {
|
||||
newLength = j-i-3;
|
||||
}
|
||||
else {
|
||||
structsFound--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(newLength != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(newLength > 0);
|
||||
OS << "\n";
|
||||
indent += 2;
|
||||
printFormattedTypeString(OS, typeStr, i+2, newLength);
|
||||
indent -= 2;
|
||||
OS << "\n";
|
||||
for(int k=0;k<indent;k++) OS << " ";
|
||||
i = j;
|
||||
OS << typeStr[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeUtil::printTypeString(raw_ostream &OS, TYPECONST Type* type,
|
||||
size_t max_chars /*= 0*/, size_t max_levels /*= 0*/) {
|
||||
static std::vector<TYPECONST Type*> nestedTypes;
|
||||
static unsigned level = 0;
|
||||
static unsigned counter;
|
||||
|
||||
if (level == 0) {
|
||||
counter = 0;
|
||||
}
|
||||
else if(max_chars && counter >= max_chars) {
|
||||
OS << "%%";
|
||||
return;
|
||||
}
|
||||
else if(max_levels && level >= max_levels) {
|
||||
OS << "%%";
|
||||
return;
|
||||
}
|
||||
|
||||
if(TypeUtil::isOpaqueTy(type)) {
|
||||
OS << "opaque";
|
||||
counter += 6;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
if(numContainedTypes == 0) {
|
||||
assert(!type->isStructTy());
|
||||
type->print(OS);
|
||||
counter += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if(type->isPointerTy() && type->getContainedType(0)->isStructTy()) {
|
||||
bool isNestedType = false;
|
||||
unsigned j;
|
||||
for(j=0;j<nestedTypes.size();j++) {
|
||||
if(nestedTypes[j] == type) {
|
||||
isNestedType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isNestedType) {
|
||||
OS << "\\" << nestedTypes.size() - j;
|
||||
counter += 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nestedTypes.push_back(type);
|
||||
if(type->isPointerTy()) {
|
||||
TYPECONST Type* subType = type->getContainedType(0);
|
||||
level++;
|
||||
printTypeString(OS, subType);
|
||||
level--;
|
||||
OS << "*";
|
||||
counter++;
|
||||
}
|
||||
else if(type->isArrayTy() || type->isVectorTy()) {
|
||||
TYPECONST Type* subType = type->getContainedType(0);
|
||||
unsigned numElements = type->isArrayTy() ? ((TYPECONST ArrayType*) type)->getNumElements() : ((TYPECONST VectorType*) type)->getNumElements();
|
||||
char startSep = type->isArrayTy() ? '[' : '<';
|
||||
char endSep = type->isArrayTy() ? ']' : '>';
|
||||
OS << startSep;
|
||||
if(numElements) {
|
||||
OS << numElements << " x ";
|
||||
}
|
||||
level++;
|
||||
printTypeString(OS, subType);
|
||||
level--;
|
||||
OS << endSep;
|
||||
counter += 4;
|
||||
}
|
||||
else if(type->isStructTy()) {
|
||||
if(PRINT_SKIP_STRUCTS || PRINT_SKIP_UNIONS) {
|
||||
OS << "$STRUCT/UNION";
|
||||
counter += 13;
|
||||
nestedTypes.pop_back();
|
||||
return;
|
||||
}
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
OS << "{ ";
|
||||
OS << "$STRUCT/UNION ";
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if(i > 0) {
|
||||
OS << ", ";
|
||||
}
|
||||
TYPECONST Type* subType = type->getContainedType(i);
|
||||
level++;
|
||||
printTypeString(OS, subType);
|
||||
level--;
|
||||
}
|
||||
OS << " }";
|
||||
counter += 18 + 2*numContainedTypes;
|
||||
}
|
||||
else if(type->isFunctionTy()) {
|
||||
unsigned numContainedTypes = type->getNumContainedTypes();
|
||||
assert(numContainedTypes > 0);
|
||||
TYPECONST Type* subType = type->getContainedType(0);
|
||||
level++;
|
||||
printTypeString(OS, subType);
|
||||
level--;
|
||||
numContainedTypes--;
|
||||
OS << " (";
|
||||
for(unsigned i=0;i<numContainedTypes;i++) {
|
||||
if(i > 0) {
|
||||
OS << ", ";
|
||||
}
|
||||
subType = type->getContainedType(i+1);
|
||||
level++;
|
||||
printTypeString(OS, subType);
|
||||
level--;
|
||||
}
|
||||
OS << ")";
|
||||
counter += 3 + 2*numContainedTypes;
|
||||
}
|
||||
else {
|
||||
OS << "???";
|
||||
counter +=3;
|
||||
}
|
||||
nestedTypes.pop_back();
|
||||
}
|
||||
|
||||
unsigned TypeUtil::typeToBits(TYPECONST Type *type) {
|
||||
if (type->isIntegerTy()) {
|
||||
return ((IntegerType*)type)->getBitWidth();
|
||||
}
|
||||
else if (type->isArrayTy() && type->getContainedType(0)->isIntegerTy()) {
|
||||
TYPECONST Type *containedType = type->getContainedType(0);
|
||||
return ((IntegerType*)containedType)->getBitWidth() * ((ArrayType*)containedType)->getNumElements();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TypeUtil::VERBOSE_LEVEL = 1;
|
||||
int TypeUtil::PRINT_SKIP_UNIONS = 0;
|
||||
int TypeUtil::PRINT_SKIP_STRUCTS = 0;
|
||||
int TypeUtil::PRINT_USE_BUILTIN_PRINTING = 0;
|
||||
int TypeUtil::PRINT_MULTI_NAMES = 0;
|
||||
|
||||
}
|
68
minix/llvm/passes/magic/support/VariableRefs.cpp
Normal file
68
minix/llvm/passes/magic/support/VariableRefs.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include <magic/support/VariableRefs.h>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Constructors, destructor, and operators
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
VariableRefs::VariableRefs() {
|
||||
clear();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Getters
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool VariableRefs::isUnnecessaryInstruction(Instruction* inst) const {
|
||||
//have already instruction in the entry block, skip
|
||||
if(instructionInEntryBlock) {
|
||||
return true;
|
||||
}
|
||||
//have already instruction in the same block, skip
|
||||
if(instruction && inst->getParent() == instruction->getParent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Instruction* VariableRefs::getInstruction() const {
|
||||
return instruction;
|
||||
}
|
||||
|
||||
bool VariableRefs::isInstructionInEntryBlock() const {
|
||||
return instructionInEntryBlock;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other public methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void VariableRefs::addInstruction(Instruction* inst) {
|
||||
//no instruction yet, update instruction
|
||||
if(!instruction) {
|
||||
instruction = inst;
|
||||
return;
|
||||
}
|
||||
//have already instruction in another block, give up and resort to a single instruction in the entry block
|
||||
setFunctionEntryInstruction(inst->getParent()->getParent());
|
||||
}
|
||||
|
||||
void VariableRefs::clear() {
|
||||
instruction = NULL;
|
||||
instructionInEntryBlock = false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Private methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void VariableRefs::setFunctionEntryInstruction(Function* function) {
|
||||
this->instruction = function->front().getFirstNonPHI();
|
||||
this->instructionInEntryBlock = true;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue