]> Zhao Yanbai Git Server - minix.git/commitdiff
Import magic pass from llvm-apps 42/3142/1
authorDavid van Moolenbroek <david@minix3.org>
Mon, 29 Jun 2015 23:25:43 +0000 (01:25 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 17 Sep 2015 13:57:53 +0000 (13:57 +0000)
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8

33 files changed:
minix/llvm/include/common/util/stdlib.h [new file with mode: 0644]
minix/llvm/include/common/util/util_def.h [new file with mode: 0644]
minix/llvm/include/magic_common.h [new file with mode: 0644]
minix/llvm/passes/hello/hello.cpp
minix/llvm/passes/hello/pass_hello.h [deleted file]
minix/llvm/passes/include/common/pass_common.h [new file with mode: 0644]
minix/llvm/passes/include/common/qprof_common.h [new file with mode: 0644]
minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h [new file with mode: 0644]
minix/llvm/passes/include/magic/MagicCheckpointPass.h [new file with mode: 0644]
minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h [new file with mode: 0644]
minix/llvm/passes/include/magic/MagicPass.h [new file with mode: 0644]
minix/llvm/passes/include/magic/magic.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/Backports.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/BitFieldAggregation.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/EDIType.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/MagicDebugFunction.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/MagicMemFunction.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/MagicUtil.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/SmartType.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/TypeInfo.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/TypeUtil.h [new file with mode: 0644]
minix/llvm/passes/include/magic/support/VariableRefs.h [new file with mode: 0644]
minix/llvm/passes/include/pass.h [moved from minix/llvm/passes/hello/pass.h with 95% similarity]
minix/llvm/passes/magic/MagicPass.cpp [new file with mode: 0644]
minix/llvm/passes/magic/Makefile [new file with mode: 0644]
minix/llvm/passes/magic/support/Backports.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/BitFieldAggregation.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/EDIType.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/MagicUtil.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/SmartType.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/TypeUtil.cpp [new file with mode: 0644]
minix/llvm/passes/magic/support/VariableRefs.cpp [new file with mode: 0644]

diff --git a/minix/llvm/include/common/util/stdlib.h b/minix/llvm/include/common/util/stdlib.h
new file mode 100644 (file)
index 0000000..19a3c6d
--- /dev/null
@@ -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 */
+
diff --git a/minix/llvm/include/common/util/util_def.h b/minix/llvm/include/common/util/util_def.h
new file mode 100644 (file)
index 0000000..eff7a4b
--- /dev/null
@@ -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
+
diff --git a/minix/llvm/include/magic_common.h b/minix/llvm/include/magic_common.h
new file mode 100644 (file)
index 0000000..7f9d2f1
--- /dev/null
@@ -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 */
+
index 5d7f9dc6c1206fd4942c5dc29a2f3fe9d951651f..8ca5686de161c3a95d6307d401db471bfcbab6fd 100644 (file)
@@ -1,4 +1,4 @@
-#include "pass_hello.h"
+#include <pass.h>
 #include <stdlib.h>
 
 using namespace llvm;
diff --git a/minix/llvm/passes/hello/pass_hello.h b/minix/llvm/passes/hello/pass_hello.h
deleted file mode 100644 (file)
index 9d1f15e..0000000
+++ /dev/null
@@ -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 */
diff --git a/minix/llvm/passes/include/common/pass_common.h b/minix/llvm/passes/include/common/pass_common.h
new file mode 100644 (file)
index 0000000..6590621
--- /dev/null
@@ -0,0 +1,1011 @@
+#ifndef _PASS_COMMON_H
+#define _PASS_COMMON_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>
+#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 FOREACH_FUNC(M, F, B) do { \
+    Module::FunctionListType &__FL = (M).getFunctionList(); \
+    for (Module::iterator __MI = __FL.begin(); __MI != __FL.end(); ++__MI) { \
+        const Function *F = __MI; \
+        if (F->isIntrinsic()) \
+            continue; \
+        B \
+    } \
+} while(0)
+
+#define FOREACH_FUNC_INS(F, I, B) do { \
+    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) { \
+            Instruction *I = (Instruction*) ((unsigned long) &(*__BI)); \
+            B \
+        } \
+    } \
+} while(0)
+
+#define FOREACH_FUNC_CS(F, CS, B) do { \
+    FOREACH_FUNC_INS(F, I, \
+        CallSite CS = PassUtil::getCallSiteFromInstruction(I); \
+        if (!CS.getInstruction()) \
+            continue; \
+        B \
+    ); \
+} while(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 void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
+      static const std::string getTypeDescription(TYPECONST Type* type);
+      static Value *findDbgGlobalDeclare(GlobalVariable *V);
+      static Value *findDbgSubprogramDeclare(const Function *F);
+      static void getDbgLocationInfoRelPath(const std::string &baseDir, const std::string &filename, const std::string &directory, std::string &relPath);
+      static void getDbgLocationInfo(DIDescriptor &DID, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath);
+      static bool getInstrDbgLocationInfo(Instruction *I, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath, unsigned int *lineNum, bool expand=true);
+      static unsigned getDbgSubrangeNumElements(const DISubrange &subrange);
+      static bool isDbgVectorTy(const DIType &type);
+      static DIType getDITypeDerivedFrom(const DIDerivedType &type);
+      static bool isOpaqueTy(TYPECONST Type *type);
+      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 FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &argsTy, bool isVarArg=false);
+      static Function* setFunctionProperties(Function *F, unsigned long properties);
+      static Function* createFunctionWeakPtrWrapper(Module &M, StringRef Name, FunctionType *Ty);
+      static Function* getOrInsertFunction(Module &M, StringRef Name, FunctionType *Ty, PassUtilLinkageType insertLinkage, unsigned long properties);
+      static PassUtilLinkageType getFunctionPassUtilLinkageType(Function *F);
+      static std::string getPassUtilLinkageTypeString(PassUtilLinkageType linkageType);
+      static void getFunctionEntryExits(Function *F, BasicBlock **entryBlock, std::vector<BasicBlock*> *exitBlocks);
+      static bool isReturnedValue(Function *F, Value *V);
+      static CallSite getCallSiteFromInstruction(Instruction *I);
+      static CallSite getCallSiteFromUser(User *U);
+      static void getFunctionsInDirectBUCallgraph(Function* F, std::set<Function*> &funcs);
+      static void getAllocaInfo(Function *F, Instruction **allocaInsertionPoint, Instruction **firstNonAllocaInst);
+      static Constant* getStringConstantArray(Module &M, const std::string &string);
+      static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName = ".str.pu", const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false);
+      static ATTRIBUTE_SET_TY remapCallSiteAttributes(CallSite &CS, int argOffset);
+      static void parseStringListOpt(std::vector<std::string> &vector, const std::string &string, const std::string &separator = ":");
+      static void parseStringPairListOpt(std::set<std::pair<std::string, std::string> > &set, const std::string &string, const std::string &listSeparator = ":", const std::string &pairSeparator = ";");
+      static void parseRegexListOpt(std::vector<Regex*> &list, const std::string &string);
+      static bool matchRegexes(std::string string, std::vector<Regex*> &regexes);
+      static void setModule(Module *M);
+      static void getModuleName(Module &M, std::string *fullName, std::string *dirName, std::string *baseName);
+      static unsigned long getTypeHash(TYPECONST Type* type, unsigned maxLevel=11);
+  private:
+      static Module *M;
+};
+
+inline void PassUtil::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
+#if LLVM_VERSION >= 30
+    /* XXX Check. */
+    type->print(OS);
+    return;
+#else
+    return WriteTypeSymbolic(OS, type, M);
+#endif
+}
+
+inline const std::string PassUtil::getTypeDescription(TYPECONST Type* type) {
+    std::string string;
+#if LLVM_VERSION >= 30
+    /* XXX Check. */
+    raw_string_ostream ostream(string);
+    type->print(ostream);
+    ostream.flush();
+#else
+    string = type->getDescription();
+#endif
+
+    return string;
+}
+
+inline Value *PassUtil::findDbgGlobalDeclare(GlobalVariable *V) {
+#if LLVM_VERSION >= 30
+  const Module *M = V->getParent();
+  NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.cu");
+  if (!NMD)
+    return 0;
+
+  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      DICompileUnit CU(NMD->getOperand(i));
+      DIArray GVs = CU.getGlobalVariables();
+      for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) {
+        DIDescriptor DIG(GVs.getElement(i));
+        if (DIGlobalVariable(DIG).getGlobal() == V)
+          return DIG;
+      }
+  }
+  return 0;
+#else
+  const Module *M = V->getParent();
+  NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
+  if (!NMD)
+    return 0;
+
+  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+    DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
+    if (!DIG.isGlobalVariable())
+      continue;
+    if (DIGlobalVariable(DIG).getGlobal() == V)
+      return DIG;
+  }
+  return 0;
+#endif
+}
+
+inline Value *PassUtil::findDbgSubprogramDeclare(const Function *V) {
+#if LLVM_VERSION >= 30
+  const Module *M = V->getParent();
+  NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.cu");
+  if (!NMD)
+    return 0;
+
+  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+      DICompileUnit CU(NMD->getOperand(i));
+      DIArray SPs = CU.getSubprograms();
+      for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
+           DISubprogram DIS(SPs.getElement(i));
+           if (DIS.getFunction() == V) {
+               return DIS;
+           }
+      }
+  }
+  return 0;
+#else
+  const Module *M = V->getParent();
+  NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp");
+  if (!NMD)
+    return 0;
+
+  for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+    DIDescriptor DIG(cast<MDNode>(NMD->getOperand(i)));
+    if (!DIG.isSubprogram())
+      continue;
+    if (DISubprogram(DIG).getFunction() == V)
+      return DIG;
+  }
+  return 0;
+#endif
+}
+
+inline void PassUtil::getDbgLocationInfoRelPath(const std::string &baseDir, const std::string &filename, const std::string &directory, std::string &relPath) {
+    StringRef directoryRef(directory);
+    std::pair<StringRef, StringRef> stringPair = directoryRef.split(baseDir);
+    relPath = (stringPair.second.compare("") ? stringPair.second.str() : stringPair.first.str()) + "/" + filename;
+#if DEBUG_LLVM_DEBUG_API
+    errs() << " - getDbgLocationInfoRelPath: Location Info is: " << directory << " | " << filename << " | " << relPath << "\n";
+#endif
+}
+
+inline void PassUtil::getDbgLocationInfo(DIDescriptor &DID, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath) {
+  StringRef _directory;
+  StringRef _filename;
+  if (DID.isGlobalVariable()) {
+#if LLVM_VERSION >= 30
+    _directory = ((DIGlobalVariable*)&DID)->getDirectory();
+    _filename = ((DIGlobalVariable*)&DID)->getFilename();
+#else
+    _directory = ((DIGlobalVariable*)&DID)->getCompileUnit().getDirectory();
+    _filename = ((DIGlobalVariable*)&DID)->getCompileUnit().getFilename();
+#endif
+#if DEBUG_LLVM_DEBUG_API
+    errs() << "DIGlobalVariable name is: " << ((DIGlobalVariable*)&DID)->getName() << "\n";
+#endif
+  }
+  else if (DID.isSubprogram()) {
+    _directory = ((DISubprogram*)&DID)->getDirectory();
+    _filename = ((DISubprogram*)&DID)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+    errs() << "DISubprogram name is: " << ((DISubprogram*)&DID)->getName() << "\n";
+#endif
+  }
+  else {
+    DIScope DIS;
+    assert (DID.isVariable());
+    DIS = ((DIVariable*)&DID)->getContext();
+    if (DIS.isSubprogram()) {
+        _directory = ((DISubprogram*)&DIS)->getDirectory();
+        _filename = ((DISubprogram*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+        errs() << "DIVariable (SP) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+    }
+    else if (DIS.isLexicalBlock()) {
+        _directory = ((DILexicalBlock*)&DIS)->getDirectory();
+        _filename = ((DILexicalBlock*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+        errs() << "DIVariable (LB) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+    }
+    else {
+#if LLVM_VERSION >= 30
+        assert(DIS.isLexicalBlockFile());
+        _directory = ((DILexicalBlockFile*)&DIS)->getDirectory();
+        _filename = ((DILexicalBlockFile*)&DIS)->getFilename();
+#if DEBUG_LLVM_DEBUG_API
+        errs() << "DIVariable (LBF) name is: " << ((DIVariable*)&DID)->getName() << "\n";
+#endif
+#else
+       assert(0 && "Unexpected DIScope instance!");
+#endif
+    }
+  }
+  if (filename) {
+    *filename = _filename;
+  }
+  if (directory) {
+    *directory = _directory;
+  }
+  if (relPath) {
+    getDbgLocationInfoRelPath(baseDir, _filename, _directory, *relPath);
+  }
+}
+
+inline bool PassUtil::getInstrDbgLocationInfo(Instruction *I, const std::string &baseDir, std::string *filename, std::string *directory, std::string *relPath, unsigned int *lineNum, bool expand) {
+    BasicBlock::iterator BI = I;
+    MDNode *N = BI->getMetadata("dbg");
+    if (!N && !expand) {
+        return false;
+    }
+    while(!N) {
+        if (BI->isTerminator()) {
+            BranchInst *BInst = dyn_cast<BranchInst>(BI);
+            if (BInst && BInst->isUnconditional()) {
+                BI = BInst->getSuccessor(0)->front();
+                N = BI->getMetadata("dbg");
+                continue;
+            }
+            return false;
+        }
+        BI++;
+        N = BI->getMetadata("dbg");
+    }
+
+    DILocation DIL(N);
+    StringRef _directory = DIL.getDirectory();
+    StringRef _filename = DIL.getFilename();
+    if (filename) {
+        *filename = _filename;
+    }
+    if (directory) {
+        *directory = _directory;
+    }
+    if (relPath) {
+      getDbgLocationInfoRelPath(baseDir, _filename, _directory, *relPath);
+    }
+    if (lineNum) {
+        *lineNum = DIL.getLineNumber();
+    }
+
+    return true;
+}
+
+inline unsigned PassUtil::getDbgSubrangeNumElements(const DISubrange &subrange) {
+#if LLVM_VERSION >= 33
+    const unsigned numElements = (unsigned) subrange.getCount();
+#else
+    const unsigned low = (unsigned) subrange.getLo();
+    const unsigned high = (unsigned) subrange.getHi();
+    const unsigned numElements = high - low + 1;
+#endif
+
+    return numElements;
+}
+
+inline bool PassUtil::isDbgVectorTy(const DIType &type) {
+#if LLVM_VERSION >= 33
+    return type.isVector();
+#else
+    return type.getTag() == dwarf::DW_TAG_vector_type;
+#endif
+}
+
+inline DIType PassUtil::getDITypeDerivedFrom(const DIDerivedType &type) {
+#if LLVM_VERSION >= 34
+    static DITypeIdentifierMap TypeIdentifierMap;
+    static bool TypeMapInitialized = false;
+    if (!TypeMapInitialized) {
+        assert(PassUtil::M && "Set module first!");
+        if (NamedMDNode *CU_Nodes = PassUtil::M->getNamedMetadata("llvm.dbg.cu")) {
+          TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
+          TypeMapInitialized = true;
+        }
+    }
+    return type.getTypeDerivedFrom().resolve(TypeIdentifierMap);
+#else
+    return type.getTypeDerivedFrom();
+#endif
+}
+
+inline bool PassUtil::isOpaqueTy(TYPECONST Type *type) {
+#if LLVM_VERSION >= 30
+    return type->isStructTy() && (((TYPECONST StructType*)type)->isOpaque() || type->getNumContainedTypes() == 0);
+#else
+    return type->isOpaqueTy();
+#endif
+}
+
+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 GetElementPtrInst* PassUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
+#if LLVM_VERSION >= 30
+    ArrayRef<Value*> ref(indexes);
+    return GetElementPtrInst::Create(ptr, ref, NameStr, InsertBefore);
+#else
+    return GetElementPtrInst::Create(ptr, indexes.begin(), indexes.end(), NameStr, InsertBefore);
+#endif
+}
+
+inline GetElementPtrInst* PassUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+#if LLVM_VERSION >= 30
+    ArrayRef<Value*> ref(indexes);
+    return GetElementPtrInst::Create(ptr, ref, NameStr, InsertAtEnd);
+#else
+    return GetElementPtrInst::Create(ptr, indexes.begin(), indexes.end(), NameStr, InsertAtEnd);
+#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 Function* PassUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
+#if LLVM_VERSION >= 30
+    std::vector<TYPECONST Type*> typeVector;
+    for(unsigned i=0;i<size;i++) {
+        typeVector.push_back(types[i]);
+    }
+    ArrayRef<TYPECONST Type*> ref(typeVector);
+    return Intrinsic::getDeclaration(&M, id, ref);
+#else
+    return Intrinsic::getDeclaration(&M, id, types, size);
+#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 Function* PassUtil::setFunctionProperties(Function *F, unsigned long props)
+{
+    assert(F);
+    bool preserve = props & (PASS_UTIL_FLAG(PASS_UTIL_PROP_NOINLINE)|PASS_UTIL_FLAG(PASS_UTIL_PROP_USED)|PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+
+    if (F->isDeclaration()) {
+        return F;
+    }
+    if (preserve) {
+        Instruction *I;
+        getAllocaInfo(F, NULL, &I);
+        assert(I);
+
+        /* Add a volatile store to a new global variable to preserve it. */
+        PointerType* voidPointerTy = PointerType::get(IntegerType::get(F->getContext(), 8), 0);
+        GlobalVariable* volatileVar = new GlobalVariable(*F->getParent(),
+            voidPointerTy, false, GlobalValue::CommonLinkage,
+            0, F->getName() + "_llvm_propvar");
+        volatileVar->setInitializer(ConstantPointerNull::get(voidPointerTy));
+        new StoreInst(ConstantExpr::getCast(Instruction::BitCast, F, voidPointerTy), volatileVar, true, I);
+    }
+    return F;
+}
+
+inline Function* PassUtil::createFunctionWeakPtrWrapper(Module &M, StringRef Name, FunctionType *Ty)
+{
+    unsigned i;
+    Function *F = getOrInsertFunction(M, Name.str() + "_llvm_weakptrwrapper" , Ty, PASS_UTIL_LINKAGE_COMMON, 0);
+    TYPECONST Type *RetTy = Ty->getReturnType();
+    PointerType *FPtrTy = PointerType::get(Ty, 0);
+    Constant *FPtrNull = Constant::getNullValue(FPtrTy);
+
+    /* Create the global function pointer variable. */
+    GlobalVariable* weakPtrVar = new GlobalVariable(M, FPtrTy, false,
+        GlobalValue::CommonLinkage, 0, Name);
+    weakPtrVar->setInitializer(FPtrNull);
+
+    /* Create the wrapper function body. */
+    F->dropAllReferences();
+    BasicBlock* entryBB = BasicBlock::Create(M.getContext(), "entry",F,0);
+    BasicBlock* weakPtrOverridenBB = BasicBlock::Create(M.getContext(), "have." + Name.str(),F,0);
+    BasicBlock* endBB = BasicBlock::Create(M.getContext(), "end",F,0);
+    AllocaInst* retval = NULL;
+
+    /* Parse arguments. */
+    std::vector<AllocaInst*> argsAllocaInsts;
+    for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++) {
+        Value *argValue = args;
+        AllocaInst *allocaInst = new AllocaInst(argValue->getType(), ".llvm.pu.args", entryBB);
+        argsAllocaInsts.push_back(allocaInst);
+    }
+    if (!RetTy->isVoidTy()) {
+        retval = new AllocaInst(RetTy, "retval", entryBB);
+    }
+    i=0;
+    for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++, i++) {
+        Value *argValue = args;
+        AllocaInst *allocaInst = argsAllocaInsts[i];
+        new StoreInst(argValue, allocaInst, true, entryBB);
+    }
+    if (retval) {
+        new StoreInst(Constant::getNullValue(RetTy), retval, true, entryBB);
+    }
+
+    /* Build entry block. */
+    LoadInst* weakPtr = new LoadInst(weakPtrVar, "", true, entryBB);
+    ICmpInst* cmpInst = new ICmpInst(*entryBB, ICmpInst::ICMP_NE, weakPtr, FPtrNull, "");
+    BranchInst::Create(weakPtrOverridenBB, endBB, cmpInst, entryBB);
+
+    /* Build weakPtrOverriden block, only executed with a non-NULL weakPtr */
+    std::vector<Value*> weakPtrCallParams;
+    i=0;
+    for (Function::arg_iterator args = F->arg_begin(); args != F->arg_end(); args++, i++) {
+        AllocaInst *allocaInst = argsAllocaInsts[i];
+        weakPtrCallParams.push_back(new LoadInst(allocaInst, "", true, weakPtrOverridenBB));
+    }
+    weakPtr = new LoadInst(weakPtrVar, "", true, weakPtrOverridenBB);
+    CallInst* weakPtrCall = createCallInstruction(weakPtr, weakPtrCallParams, "", weakPtrOverridenBB);
+    weakPtrCall->setCallingConv(CallingConv::C);
+
+    if (retval) {
+        new StoreInst(weakPtrCall, retval, false, weakPtrOverridenBB);
+    }
+    BranchInst::Create(endBB, weakPtrOverridenBB);
+
+    /* Build end block. */
+    if (!retval) {
+        ReturnInst::Create(M.getContext(), endBB);
+    }
+    else {
+        LoadInst* retvalValue = new LoadInst(retval, "", false, endBB);
+        ReturnInst::Create(M.getContext(), retvalValue, endBB);
+    }
+    return F;
+}
+
+inline Function* PassUtil::getOrInsertFunction(Module &M, StringRef Name, FunctionType *Ty, PassUtilLinkageType insertLinkage, unsigned long properties)
+{
+    static std::map<std::string, Function *> functionMap;
+    std::map<std::string, Function *>::iterator functionMapIt;
+    Function *F = NULL;
+    bool needsEmptyBody = true;
+    bool needsProperties = true;
+    bool needsIncludsion = true;
+
+    functionMapIt = functionMap.find(Name);
+    if (functionMapIt != functionMap.end()) {
+        return functionMapIt->second;
+    }
+    F = M.getFunction(Name);
+
+    if (F) {
+        /* If the function exists, check the type and return it. */
+        if (F->getFunctionType() != Ty) {
+            return NULL;
+        }
+        functionMap.insert(std::pair<std::string, Function *>(Name, F));
+        setFunctionProperties(F, properties);
+        return F;
+    }
+
+    /* Has the user requested creation of the function otherwise? */
+    if (insertLinkage == PASS_UTIL_LINKAGE_NONE) {
+        return NULL;
+    }
+    switch(insertLinkage) {
+    case PASS_UTIL_LINKAGE_WEAK:
+        /* Create empty function that can optionally be overriden at link time*/
+        F = Function::Create(Ty, GlobalVariable::WeakAnyLinkage, Name);
+    break;
+    case PASS_UTIL_LINKAGE_COMMON:
+        /* Creates empty function, non overridable. */
+        F = Function::Create(Ty, GlobalVariable::InternalLinkage, Name);
+    break;
+    case PASS_UTIL_LINKAGE_EXTERNAL:
+        /* Creates function declaration that must be defined at link time. */
+        F = Function::Create(Ty, GlobalVariable::ExternalLinkage, Name);
+        needsEmptyBody = false;
+    break;
+    case PASS_UTIL_LINKAGE_EXTERNAL_WEAK:
+        /* Creates weak function declaration that can optionally be defined
+         * at link time (if undefined the linker will emit a NULL symbol).
+         */
+        F = Function::Create(Ty, GlobalVariable::ExternalWeakLinkage, Name);
+        needsEmptyBody = false;
+    break;
+    case PASS_UTIL_LINKAGE_WEAK_POINTER:
+        /* Creates function pointer initialized to NULL that can optionally
+         * be initialized at runtime. Invocations are wrapped to ensure that
+         * indirect call is performed on a NULL pointer. This is to emulate
+         * Mac OS' weak_pointer attribute, which allows weak symbols to be
+         * overriden in LD_PRELOADED libraries at runtime.
+         */
+        F = PassUtil::createFunctionWeakPtrWrapper(M, Name, Ty);
+        needsProperties = false;
+        needsIncludsion = false;
+    break;
+    default:
+        return NULL;
+    break;
+    }
+    if (needsIncludsion) {
+        M.getFunctionList().push_back(F);
+    }
+    if (needsEmptyBody) {
+        BasicBlock* block = BasicBlock::Create(M.getContext(), "entry", F);
+        IRBuilder<> builder(block);
+        TYPECONST Type *RetTy = Ty->getReturnType();
+        if (RetTy->isVoidTy()) {
+            builder.CreateRetVoid();
+        }
+        else {
+            builder.CreateRet(Constant::getNullValue(RetTy));
+        }
+    }
+    functionMap.insert(std::pair<std::string, Function *>(Name, F));
+    if (needsProperties) {
+        setFunctionProperties(F, properties);
+    }
+    return F;
+}
+
+inline PassUtilLinkageType PassUtil::getFunctionPassUtilLinkageType(Function *F)
+{
+    if (F->isDeclaration()) {
+        return PASS_UTIL_LINKAGE_EXTERNAL;
+    }
+    if (F->hasInternalLinkage()) {
+        return PASS_UTIL_LINKAGE_PRIVATE;
+    }
+    return PASS_UTIL_LINKAGE_COMMON;
+}
+
+inline std::string PassUtil::getPassUtilLinkageTypeString(PassUtilLinkageType linkageType)
+{
+    const char *strArray[] = { PASS_UTIL_LINKAGE_TYPE_STRINGS };
+    std::string str(strArray[linkageType]);
+    return str;
+}
+
+inline void PassUtil::getFunctionEntryExits(Function *F, BasicBlock **entryBlock, std::vector<BasicBlock*> *exitBlocks)
+{
+    if (entryBlock) {
+        *entryBlock = &F->front();
+    }
+    if (exitBlocks) {
+        for(Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+            if (isa<ReturnInst>(I->getTerminator()) || isa<UnreachableInst>(I->getTerminator()))
+                exitBlocks->push_back(I);
+        }
+    }
+}
+
+inline bool PassUtil::isReturnedValue(Function *F, Value *V)
+{
+    std::vector<BasicBlock*> exitBlocks;
+    PassUtil::getFunctionEntryExits(F, NULL, &exitBlocks);
+    for (unsigned i=0;i<exitBlocks.size();i++) {
+        Instruction *I = exitBlocks[i]->getTerminator();
+        ReturnInst *RI = dyn_cast<ReturnInst>(I);
+        if (RI && RI->getReturnValue()) {
+            Value *RV = RI->getReturnValue();
+            if (RV == V) {
+                return true;
+            }
+            if (LoadInst *LI = dyn_cast<LoadInst>(RV)) {
+                if (LI->getPointerOperand() == V) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+inline CallSite PassUtil::getCallSiteFromInstruction(Instruction *I)
+{
+  return getCallSiteFromUser(I);
+}
+
+inline CallSite PassUtil::getCallSiteFromUser(User *U)
+{
+  CallSite CS(U->stripPointerCasts());
+  CallSite emptyCS;
+  Instruction *I = CS.getInstruction();
+  if (!I)
+      return emptyCS;
+  if (isa<CallInst>(I) && dyn_cast<CallInst>(I)->isInlineAsm())
+      return emptyCS;
+  Function *F = CS.getCalledFunction();
+  if (F && F->isIntrinsic())
+      return emptyCS;
+  return CS;
+}
+
+inline void PassUtil::getFunctionsInDirectBUCallgraph(Function* F, std::set<Function*> &funcs) {
+  if (funcs.find(F) != funcs.end())
+      return;
+  funcs.insert(F);
+  FOREACH_FUNC_CS(F, CS,
+      if (!CS.getCalledFunction())
+          continue;
+      getFunctionsInDirectBUCallgraph(CS.getCalledFunction(), funcs);
+  );
+}
+
+inline void PassUtil::getAllocaInfo(Function *F, Instruction **allocaInsertionPoint, Instruction **firstNonAllocaInst)
+{
+    assert(!F->isDeclaration());
+    BasicBlock::iterator allocaIP = F->front().begin();
+    while (isa<AllocaInst>(allocaIP)) ++allocaIP;
+    BasicBlock::iterator firstNonAI = allocaIP;
+    if (firstNonAI->getName().equals("alloca point")) {
+       firstNonAI++;
+    }
+    if(allocaInsertionPoint) {
+       *allocaInsertionPoint = allocaIP;
+    }
+    if(firstNonAllocaInst) {
+       *firstNonAllocaInst = firstNonAI;
+    }
+}
+
+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;
+}
+
+inline ATTRIBUTE_SET_TY PassUtil::remapCallSiteAttributes(CallSite &CS, int argOffset)
+{
+    ATTRIBUTE_SET_TY Attrs = CS.getAttributes();
+    ATTRIBUTE_SET_TY NewAttrs;
+#if LLVM_VERSION >= 33
+    Instruction *I = CS.getInstruction();
+    NewAttrs.addAttributes(I->getContext(), ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+    NewAttrs.addAttributes(I->getContext(), ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+    for (unsigned i=1;i<=CS.arg_size();i++) {
+        NewAttrs.addAttributes(I->getContext(), i+argOffset, Attrs.getParamAttributes(i));
+    } 
+#elif LLVM_VERSION == 32
+    Instruction *I = CS.getInstruction();
+    NewAttrs.addAttr(I->getContext(), ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+    NewAttrs.addAttr(I->getContext(), ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+    for (unsigned i=1;i<=CS.arg_size();i++) {
+        NewAttrs.addAttr(I->getContext(), i+argOffset, Attrs.getParamAttributes(i));
+    } 
+#else
+    NewAttrs.addAttr(ATTRIBUTE_SET_RET_IDX, Attrs.getRetAttributes());
+    NewAttrs.addAttr(ATTRIBUTE_SET_FN_IDX, Attrs.getFnAttributes());
+    for (unsigned i=1;i<=CS.arg_size();i++) {
+        NewAttrs.addAttr(i+argOffset, Attrs.getParamAttributes(i));
+    }
+#endif
+
+    return NewAttrs;
+}
+
+inline void PassUtil::parseStringListOpt(std::vector<std::string> &list, const std::string &string, const std::string &separator)
+{
+    if(string.compare("")) {
+        SmallVector< StringRef, 8 > vector;
+        StringRef sref(string);
+        sref.split(vector, separator, -1, false);
+        list.insert(list.end(), vector.begin(), vector.end());
+    }
+}
+
+inline void PassUtil::parseStringPairListOpt(std::set<std::pair<std::string, std::string> > &set, const std::string &string, const std::string &listSeparator, const std::string &pairSeparator)
+{
+       if(string.compare("")) {
+               SmallVector< StringRef, 8 > vector;
+               StringRef sref(string);
+               sref.split(vector, listSeparator, -1, false);
+               SmallVector< StringRef, 8 > parts;
+               while(!vector.empty()) {
+                       StringRef token = vector.pop_back_val();
+                       parts.clear();
+                       token.split(parts, pairSeparator, -1, false);
+                       assert(parts.size() == 2 && "Two tokens were expected.");
+                       set.insert(std::pair<std::string, std::string>(parts.front(), parts.back()));
+               }
+       }
+}
+
+inline void PassUtil::parseRegexListOpt(std::vector<Regex*> &list, const std::string &string)
+{
+    std::vector<std::string> stringList;
+    std::vector<std::string>::iterator it;
+    PassUtil::parseStringListOpt(stringList, string);
+
+    for (it = stringList.begin(); it != stringList.end(); ++it) {
+        Regex* regex = new Regex(*it, 0);
+        std::string error;
+        assert(regex->isValid(error));
+        list.push_back(regex);
+    }
+}
+
+inline bool PassUtil::matchRegexes(std::string string, std::vector<Regex*> &regexes)
+{
+    for (std::vector<Regex*>::iterator it = regexes.begin(); it != regexes.end(); ++it) {
+       Regex *regex = *it;
+       if(regex->match(string, NULL)) {
+           return true;
+       }
+    }
+
+    return false;
+}
+
+inline void PassUtil::setModule(Module *M)
+{
+    PassUtil::M = M;
+}
+
+inline void PassUtil::getModuleName(Module &M, std::string *fullName, std::string *dirName, std::string *baseName)
+{
+    std::string _fullName, _dirName, _baseName;
+    _fullName = M.getModuleIdentifier();
+    SmallVector< StringRef, 8 > vector;
+    StringRef fullNameRef(_fullName);
+    fullNameRef.split(vector, "/", -1, false);
+    if (vector.size() > 1) {
+        _baseName = vector.pop_back_val();
+        for (unsigned i=0;i<vector.size();i++) {
+            _dirName.append("/");
+            _dirName.append(vector[i]);
+        }
+    }
+    else {
+        _baseName = _fullName;
+        _dirName = "/";
+    }
+    vector.clear();
+    StringRef baseNameRef(_baseName);
+    baseNameRef.split(vector, ".", -1, false);
+    if (vector.size() > 1) {
+        _baseName = vector[0];
+    }
+    if (fullName)
+        *fullName = _fullName;
+    if (dirName)
+        *dirName = _dirName;
+    if (baseName)
+        *baseName = _baseName;
+}
+
+inline unsigned long PassUtil::getTypeHash(TYPECONST Type* type, unsigned maxLevel)
+{
+    static std::vector<TYPECONST Type*> nestedTypes;
+    static unsigned level = 0;
+    static unsigned counter;
+    unsigned long hash = 7;
+    if(level == 0) {
+        counter = 0;
+    }
+    unsigned numContainedTypes = type->getNumContainedTypes();
+    unsigned nestedIndex = 0;
+    for(unsigned i=0;i<nestedTypes.size();i++) {
+        if(type == nestedTypes[i]) {
+            nestedIndex = i+1;
+            break;
+        }
+    }
+    hash = (13*hash) ^ level;
+    hash = (13*hash) ^ counter++;
+    hash = (13*hash) ^ type->getTypeID();
+    hash = (13*hash) ^ nestedIndex;
+    if(TYPECONST IntegerType *intType = dyn_cast<IntegerType>(type)) {
+        hash = (13*hash) ^ intType->getBitWidth();
+    }
+    else if(TYPECONST PointerType *ptrType = dyn_cast<PointerType>(type)) {
+        hash = (13*hash) ^ ptrType->getElementType()->getTypeID();
+    }
+    if(nestedIndex > 0 || level >= maxLevel) {
+        return hash;
+    }
+    if(numContainedTypes == 0) {
+        return hash;
+    }
+    level++;
+    nestedTypes.push_back(type);
+    hash = (13*hash) ^ numContainedTypes;
+    for(unsigned i=0;i<numContainedTypes;i++) {
+        hash = (13*hash) ^ getTypeHash(type->getContainedType(i), maxLevel);
+    }
+    nestedTypes.pop_back();
+    level--;
+
+    return hash;
+}
+
+}
+
+#endif /* _PASS_COMMON_H */
diff --git a/minix/llvm/passes/include/common/qprof_common.h b/minix/llvm/passes/include/common/qprof_common.h
new file mode 100644 (file)
index 0000000..c61296f
--- /dev/null
@@ -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 */
diff --git a/minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h b/minix/llvm/passes/include/magic/MagicCTLazyCheckpointPass.h
new file mode 100644 (file)
index 0000000..f515df5
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/MagicCheckpointPass.h b/minix/llvm/passes/include/magic/MagicCheckpointPass.h
new file mode 100644 (file)
index 0000000..0858de8
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h b/minix/llvm/passes/include/magic/MagicLTLazyCheckpointPass.h
new file mode 100644 (file)
index 0000000..88681fa
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/MagicPass.h b/minix/llvm/passes/include/magic/MagicPass.h
new file mode 100644 (file)
index 0000000..cb5ffa9
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/magic.h b/minix/llvm/passes/include/magic/magic.h
new file mode 100644 (file)
index 0000000..8b820a7
--- /dev/null
@@ -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 */
+
diff --git a/minix/llvm/passes/include/magic/support/Backports.h b/minix/llvm/passes/include/magic/support/Backports.h
new file mode 100644 (file)
index 0000000..96b9e0b
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/BitFieldAggregation.h b/minix/llvm/passes/include/magic/support/BitFieldAggregation.h
new file mode 100644 (file)
index 0000000..ac53beb
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/EDIType.h b/minix/llvm/passes/include/magic/support/EDIType.h
new file mode 100644 (file)
index 0000000..a47fb69
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/MagicDebugFunction.h b/minix/llvm/passes/include/magic/support/MagicDebugFunction.h
new file mode 100644 (file)
index 0000000..2f11616
--- /dev/null
@@ -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_ */
diff --git a/minix/llvm/passes/include/magic/support/MagicMemFunction.h b/minix/llvm/passes/include/magic/support/MagicMemFunction.h
new file mode 100644 (file)
index 0000000..7e9cedb
--- /dev/null
@@ -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
+
diff --git a/minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h b/minix/llvm/passes/include/magic/support/MagicMmapCtlFunction.h
new file mode 100644 (file)
index 0000000..e21184d
--- /dev/null
@@ -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
+
diff --git a/minix/llvm/passes/include/magic/support/MagicUtil.h b/minix/llvm/passes/include/magic/support/MagicUtil.h
new file mode 100644 (file)
index 0000000..00927c3
--- /dev/null
@@ -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 &section);
+      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
diff --git a/minix/llvm/passes/include/magic/support/SmartType.h b/minix/llvm/passes/include/magic/support/SmartType.h
new file mode 100644 (file)
index 0000000..be5c6ae
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/TypeInfo.h b/minix/llvm/passes/include/magic/support/TypeInfo.h
new file mode 100644 (file)
index 0000000..c60c945
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/TypeUtil.h b/minix/llvm/passes/include/magic/support/TypeUtil.h
new file mode 100644 (file)
index 0000000..5c77dc4
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/include/magic/support/VariableRefs.h b/minix/llvm/passes/include/magic/support/VariableRefs.h
new file mode 100644 (file)
index 0000000..0574d5a
--- /dev/null
@@ -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
similarity index 95%
rename from minix/llvm/passes/hello/pass.h
rename to minix/llvm/passes/include/pass.h
index 59e542908ac0153ce78c8d291cd6e95acd85bc9a..25db98f885fa7fdfb536d29639bdbffe9912354a 100644 (file)
@@ -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>
diff --git a/minix/llvm/passes/magic/MagicPass.cpp b/minix/llvm/passes/magic/MagicPass.cpp
new file mode 100644 (file)
index 0000000..9badbdd
--- /dev/null
@@ -0,0 +1,2877 @@
+#include <magic/MagicPass.h>
+
+using namespace llvm;
+
+PASS_COMMON_INIT_ONCE();
+
+// command-line arguments
+static cl::opt<std::string>
+DLLFName("magic-dll-function",
+    cl::desc("Specify the name of the deepest long-lived function whose stack "
+        "needs to be instrumented"),
+    cl::init(MAGIC_ENTRY_POINT), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+LibPathRegex("magic-lib-path-regex",
+    cl::desc("Specify all the colon-separated path regexes that identify directories containing "
+        "libraries. Deprecated. Use -magic-ext-lib-sections instead."),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+VoidTypeAlias("magic-void-alias",
+    cl::desc("Specify all the colon-separated type names that are to be treated as void, typically "
+        "used in custom memory management implementations"),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMFuncPrefix("magic-mmfunc-prefix",
+    cl::desc("Specify all the colon-separated prefixes that are to be used when extracting "
+        "memory management functions used in custom memory management implementations"),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMFuncPair("magic-mmfunc-pair",
+    cl::desc("Specify all the colon-separated pairs of malloc/free style memory management functions "
+        "used in custom memory management implementations. Each function is to be listed together "
+       "with a number indicating which of the input parameters is the one corresponding to its "
+       "malloc(size)/free(pointer) counterpart. Example: "
+       "\"my_smart_alloc/3;my_smart_free/3:my_custom_alloc/2;my_custom_free/1\". "
+       "The counter for arguments starts from 1."),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MMPoolFunc("magic-mm-poolfunc",
+    cl::desc("Specify a pool memory management set of functions for creating pools, destroying pools, "
+               "managing the pool buffers, reseting (reusing) pools and allocating memory blocks from the pool. "
+               "All the functions are to be listed together with a number indicating which of the input parameters"
+               "(numbering starts at 1) corresponds to the pool object. For the creation function, the pool object "
+               "can be the return value (specify 0 for return value). The block allocation function additionally "
+               "requires the number of the parameter denoting the size. Separate sets of functions using ':' and "
+               "separate multiple functions of the same type using ';'. "
+               "Example: \"my_pool_block_alloc/1/2:my_pool_create/0:my_pool_destroy/1:my_pool_alloc/1;"
+               "another_pool_alloc/1;my_pool_free/1:my_pool_reset/1\"."
+               "If there are no additional management functions, skip them. "
+               "Example: \"pool_block_alloc/1/2:pool_create:pool_destroy/1\"."),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<bool>
+EnablePoolMemReuse("magic-mpool-enable-reuse",
+    cl::desc("Enable memory reuse across pools."),
+    cl::init(false), cl::NotHidden);
+
+static cl::opt<std::string>
+MMAPCtlFunction("magic-mmap-ctlfunc",
+    cl::desc("Specify all the colon-separated mmap control functions that change low-level properties"
+        "of memory-mapped memory regions taking the start address as an argument"),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MagicDataSections("magic-data-sections",
+    cl::desc("Specify all the colon-separated magic data section regexes not to instrument"),
+    cl::init("^" MAGIC_STATIC_VARS_SECTION_PREFIX ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+MagicFunctionSections("magic-function-sections",
+    cl::desc("Specify all the colon-separated magic function section regexes not to instrument"),
+    cl::init("^" MAGIC_STATIC_FUNCTIONS_SECTION ".*$:^" UNBL_SECTION_PREFIX ".*$"), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+ExtLibSections("magic-ext-lib-sections",
+    cl::desc("Specify all the colon-separated external lib section regexes"),
+    cl::init(MAGIC_DEFAULT_EXT_LIB_SECTION_REGEX), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<std::string>
+baseBuildDir("magic-base-build-dir",
+    cl::desc("Specify the base build directory from which the pass derives relative directories for debug symbols"),
+    cl::init(""), cl::NotHidden, cl::ValueRequired);
+
+static cl::opt<bool>
+EnableShadowing("magic-enable-shadowing",
+    cl::desc("Enable state shadowing"),
+    cl::init(false), cl::NotHidden);
+
+static cl::opt<bool>
+SkipAll("magic-skip-all",
+    cl::desc("Exit immediately"),
+    cl::init(false), cl::NotHidden);
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+QPROF_DECLARE_ALL_OPTS(magic,
+    magicLLSitestacks,
+    magicDeepestLLLoops,
+    magicDeepestLLLibs,
+    magicTaskClasses
+);
+#endif
+
+#define DEBUG_TYPE_INFOS            0
+#define DEBUG_FILL_TYPE_INFOS       0
+#define DEBUG_FILL_EXT_TYPE_INFOS   0
+#define DEBUG_ALLOC_LEVEL           0
+#define DEBUG_ALLOC_BAD_TYPES       0
+#define DEBUG_CASTS                 0
+#define DEBUG_DUPLICATED_TYPE_INFOS 0
+#define DEBUG_VALUE_SET             0
+#define DEBUG_QPROF                 0
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Constructors, destructor, and operators
+//===----------------------------------------------------------------------===//
+
+MagicPass::MagicPass() : ModulePass(ID) {}
+
+unsigned TypeInfo::maxNameLength = 0;
+unsigned TypeInfo::maxTypeStringLength = 0;
+std::map<TYPECONST Type*, std::set<int> > TypeInfo::intCastTypes;
+std::map<TYPECONST Type*, std::set<TYPECONST Type*> > TypeInfo::bitCastTypes;
+std::map<TYPECONST Type*, std::set<TypeInfo*> > TypeInfo::typeMap;
+
+bool SmartType::forceRawUnions = MAGIC_FORCE_RAW_UNIONS;
+bool SmartType::forceRawBitfields = MAGIC_FORCE_RAW_BITFIELDS;
+
+Function *MagicMemFunction::lastAllocWrapper = NULL;
+std::map<std::string, Function*> MagicMemFunction::allocWrapperCache;
+std::set<Function*> MagicMemFunction::customWrapperSet;
+
+//===----------------------------------------------------------------------===//
+// Public methods
+//===----------------------------------------------------------------------===//
+
+bool MagicPass::runOnModule(Module &M) {
+    unsigned i;
+
+    if (SkipAll) {
+       return false;
+    }
+
+    magicPassLog("Running...");
+    EDIType::setModule(&M);
+    PassUtil::setModule(&M);
+
+    // initialize qprof instrumentation
+    qprofInstrumentationInit(M);
+
+    //look up magic entry point function
+    Function *magicEntryPointFunc = M.getFunction(MAGIC_ENTRY_POINT);
+    if( !magicEntryPointFunc ){
+        //if no valid entry point, we are not compiling a valid program, skip pass
+        magicPassLog("Error: no " << MAGIC_ENTRY_POINT << "() found");
+        return false;
+    }
+
+    //look up magic enabled variable
+    GlobalVariable* magicEnabled = M.getNamedGlobal(MAGIC_ENABLED);
+    if(!magicEnabled) {
+        magicPassErr("Error: no " << MAGIC_ENABLED << " variable found");
+        exit(1);
+    }
+
+    //look up magic root variable
+    GlobalVariable* magicRootVar = M.getNamedGlobal(MAGIC_ROOT_VAR_NAME);
+    if(!magicRootVar) {
+        magicPassErr("Error: no " << MAGIC_ROOT_VAR_NAME << " variable found");
+        exit(1);
+    }
+
+    //look up magic data init function and get the last instruction to add stuff in it
+    Function *magicDataInitFunc = M.getFunction(MAGIC_DATA_INIT_FUNC_NAME);
+    if(!magicDataInitFunc){
+        magicPassErr("Error: no " << MAGIC_DATA_INIT_FUNC_NAME << "() found");
+        exit(1);
+    }
+    Instruction *magicArrayBuildFuncInst = magicDataInitFunc->back().getTerminator();
+
+    //look up pointer to magic array and magic struct type
+    Value* magicArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES);
+    if(!magicArrayPtr) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES << " field found");
+        exit(1);
+    }
+    TYPECONST StructType* magicStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicArrayPtr->getType())->getElementType())->getElementType();
+
+    //look up pointer to magic array size
+    Value *magicArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NUM);
+    if(!magicArraySize) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NUM << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic array string size
+    Value *magicArrayStrSize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM);
+    if(!magicArrayStrSize) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_STR_NUM << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic next id
+    Value *magicNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID);
+    if(!magicNextId) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_SENTRIES_NEXT_ID << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic dsindex array and magic dsindex struct type
+    Value* magicDsindexArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES);
+    if(!magicDsindexArrayPtr) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES << " field found");
+        exit(1);
+    }
+    TYPECONST StructType* magicDsindexStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicDsindexArrayPtr->getType())->getElementType())->getElementType();
+
+    //look up pointer to magic dsindex array size
+    Value *magicDsindexArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM);
+    if(!magicDsindexArraySize) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_DSINDEXES_NUM << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic type array and magic type struct type
+    Value *magicTypeArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES);
+    if(!magicTypeArrayPtr) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES << " field found");
+        exit(1);
+    }
+    TYPECONST StructType* magicTypeStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicTypeArrayPtr->getType())->getElementType())->getElementType();
+
+    //look up pointer to magic type array size
+    Value *magicTypeArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NUM);
+    if(!magicTypeArraySize) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NUM << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic type next id
+    Value *magicTypeNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID);
+    if(!magicTypeNextId) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_TYPES_NEXT_ID << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic function array and magic function struct type
+    Value *magicFunctionArrayPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS);
+    if(!magicFunctionArrayPtr) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS << " field found");
+        exit(1);
+    }
+    TYPECONST StructType* magicFunctionStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFunctionArrayPtr->getType())->getElementType())->getElementType();
+
+    //look up pointer to magic function array size
+    Value *magicFunctionArraySize = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM);
+    if(!magicFunctionArraySize) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NUM << " field found");
+        exit(1);
+    }
+
+    //look up pointer to magic function next id
+    Value *magicFunctionNextId = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID);
+    if(!magicFunctionNextId) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FUNCTIONS_NEXT_ID << " field found");
+        exit(1);
+    }
+
+    //look up magic dsentry struct type 
+    Value *magicFirstDsentyPtr = MagicUtil::getMagicRStructFieldPtr(M, magicArrayBuildFuncInst, magicRootVar, MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY);
+    if(!magicFirstDsentyPtr) {
+        magicPassErr("Error: no " << MAGIC_RSTRUCT_FIELD_FIRST_DSENTRY << " field found");
+        exit(1);
+    }
+    TYPECONST StructType* magicDsentryStructType = (TYPECONST StructType*) ((TYPECONST PointerType*)((TYPECONST PointerType*)magicFirstDsentyPtr->getType())->getElementType())->getElementType();
+
+    //look up magic init function
+    Function *magicInitFunc = M.getFunction(MAGIC_INIT_FUNC_NAME);
+    if( !magicInitFunc ){
+        magicPassErr("Error: no " << MAGIC_INIT_FUNC_NAME << "() found");
+        exit(1);
+    }
+
+    //look up magic dsentry stack functions
+    Function *magicStackDsentryCreateFunc = M.getFunction(MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME);
+    if (!magicStackDsentryCreateFunc) {
+        magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_CREATE_FUNC_NAME << "() found");
+        exit(1);
+    }
+    Function *magicStackDsentryDestroyFunc = M.getFunction(MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME);
+    if (!magicStackDsentryDestroyFunc) {
+        magicPassErr("Error: no " << MAGIC_STACK_DSENTRIES_DESTROY_FUNC_NAME << "() found");
+        exit(1);
+    }
+
+    //look up deepest long-lived function
+    Function *deepestLLFunction = M.getFunction(DLLFName);
+    if (!deepestLLFunction) {
+        magicPassErr("Error: no " << DLLFName << "() found");
+        exit(1);
+    }
+
+    //lookup magic get page size function
+    Function *magicGetPageSizeFunc = M.getFunction(MAGIC_GET_PAGE_SIZE_FUNC_NAME);
+    if(!magicGetPageSizeFunc){
+        magicPassErr("Error: no " << MAGIC_GET_PAGE_SIZE_FUNC_NAME << "() found");
+        exit(1);
+    }
+
+    //look up magic void pointer
+    GlobalVariable *magicVoidPtr = M.getNamedGlobal(MAGIC_VOID_PTR_NAME);
+    if(!magicVoidPtr) {
+        magicPassErr("Error: no " << MAGIC_VOID_PTR_NAME << "variable found");
+        exit(1);
+    }
+    assert(!isMagicGV(M, magicVoidPtr));
+
+    //look up magic void array
+    GlobalVariable *magicVoidArr = M.getNamedGlobal(MAGIC_VOID_ARRAY_NAME);
+    if(!magicVoidArr) {
+        magicPassErr("Error: no " << MAGIC_VOID_ARRAY_NAME << "variable found");
+        exit(1);
+    }
+    assert(!isMagicGV(M, magicVoidArr));
+
+    //look up magic void * type pointer
+    GlobalVariable *magicVoidPtrTypePtr = M.getNamedGlobal(MAGIC_VOID_PTR_TYPE_PTR_NAME);
+    if(!magicVoidPtrTypePtr) {
+        magicPassErr("Error: no " << MAGIC_VOID_PTR_TYPE_PTR_NAME << "variable found");
+        exit(1);
+    }
+
+    //determine lib path regexes
+    PassUtil::parseStringListOpt(libPathRegexes, LibPathRegex);
+
+    //determine void type aliases
+    PassUtil::parseStringListOpt(voidTypeAliases, VoidTypeAlias);
+    std::copy( voidTypeAliases.begin(), voidTypeAliases.end(), std::inserter( voidTypeAliasesSet, voidTypeAliasesSet.end() ) );
+
+    //determine mm function prefixes
+    PassUtil::parseStringListOpt(mmFuncPrefixes, MMFuncPrefix);
+
+    //determine custom malloc/free style custom mm functions
+    PassUtil::parseStringPairListOpt(mmFuncPairs, MMFuncPair);
+
+    //determine the pool management sets of functions
+    PassUtil::parseStringListOpt(mmPoolFunctions, MMPoolFunc);
+
+    //determine mmap ctl functions
+    PassUtil::parseStringListOpt(mmapCtlFunctions, MMAPCtlFunction);
+
+    //determine magic data section regexes
+    PassUtil::parseRegexListOpt(magicDataSectionRegexes, MagicDataSections);
+
+    //determine magic function section regexes
+    PassUtil::parseRegexListOpt(magicFunctionSectionRegexes, MagicFunctionSections);
+
+    //determine magic ext lib section regexes
+    PassUtil::parseRegexListOpt(extLibSectionRegexes, ExtLibSections);
+
+    //look up inttoptr type casts
+    Module::GlobalListType &globalList = M.getGlobalList();
+    Module::FunctionListType &functionList = M.getFunctionList();
+    std::vector<TYPECONST Type*> intCastTypes;
+    std::vector<int> intCastValues;
+    std::map<TYPECONST Type*, std::set<TYPECONST Type*> > bitCastMap;
+    for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
+        Function *F = it;
+        if(isMagicFunction(M, F)) {
+            continue;
+        }
+        for (inst_iterator I2 = inst_begin(F), E2 = inst_end(F); I2 != E2; ++I2) {
+            indexCasts(M, &(*I2), intCastTypes, intCastValues, bitCastMap);
+        }
+    }
+    for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+        GlobalVariable *GV = it;
+        StringRef GVName = GV->getName();
+        if(isMagicGV(M, GV) || GVName.startswith(".str") || GVName.startswith(".arr") || GVName.startswith("C.")) {
+            continue;
+        }
+        if(GV->hasInitializer()) {
+            indexCasts(M, GV->getInitializer(), intCastTypes, intCastValues, bitCastMap);
+        }
+    }
+
+    //index and set cast maps
+    std::map<TYPECONST Type*, std::set<int> > intCastMap;
+    std::map<TYPECONST Type*, std::set<int> >::iterator intCastMapIt;
+    for(i=0;i<intCastTypes.size();i++) {
+        TYPECONST Type* type = intCastTypes[i];
+        int value = intCastValues[i];
+        intCastMapIt = intCastMap.find(type);
+        if(intCastMapIt == intCastMap.end()) {
+            std::set<int> valueSet;
+            intCastMap.insert(std::pair<TYPECONST Type*, std::set<int> >(type, valueSet));
+            intCastMapIt = intCastMap.find(type);
+        }
+        assert(intCastMapIt != intCastMap.end());
+        std::set<int> *setPtr = &(intCastMapIt->second);
+        if(setPtr->size() == 1 && *(setPtr->begin()) == 0) {
+            continue;
+        }
+        if(value == 0) {
+            setPtr->clear();
+        }
+        setPtr->insert(value);
+    }
+    TypeInfo::setIntCastTypes(intCastMap);
+    TypeInfo::setBitCastTypes(bitCastMap);
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+    //look up magic memory functions and corresponding wrappers
+    #define __X(P) #P
+    std::string magicMemFuncNames[] = { MAGIC_MEM_FUNC_NAMES };
+    std::string magicMemDeallocFuncNames[] = { MAGIC_MEMD_FUNC_NAMES };
+    #undef __X
+    int magicMemFuncAllocFlags[] = { MAGIC_MEM_FUNC_ALLOC_FLAGS };
+    std::string magicMemPrefixes[] = { MAGIC_MEM_PREFIX_STRS };
+    std::vector<std::string> llvmCallPrefixes;
+    for (std::vector<std::string>::iterator it = mmFuncPrefixes.begin(); it != mmFuncPrefixes.end(); ++it) {
+        llvmCallPrefixes.push_back(*it);
+    }
+    llvmCallPrefixes.push_back("");
+    llvmCallPrefixes.push_back("\01"); //llvm uses odd prefixes for some functions, sometimes (e.g. mmap64)
+    std::vector<MagicMemFunction> magicMemFunctions;
+    std::set<Function*> originalMagicMemFunctions;
+    for(i=0;magicMemFuncNames[i].compare("");i++) {
+        int allocFlags = magicMemFuncAllocFlags[i];
+        for(unsigned j=0;j<llvmCallPrefixes.size();j++) {
+            Function *f = M.getFunction(llvmCallPrefixes[j] + magicMemFuncNames[i]);
+            if(!f) {
+                continue;
+            }
+            TYPECONST FunctionType *fType = f->getFunctionType();
+            if(fType->getNumParams() == 0 && fType->isVarArg()) {
+                //missing function prototype, i.e. no realistic caller. Skip.
+                continue;
+            }
+            if(!magicMemFuncNames[i].compare("brk")) {
+                brkFunctions.insert(f);
+            }
+            if(!magicMemFuncNames[i].compare("sbrk")) {
+                sbrkFunctions.insert(f);
+            }
+            std::string wName, wName2;
+            Function *w = NULL, *w2 = NULL;
+            for(unsigned k=0;magicMemPrefixes[k].compare("");k++) {
+                wName = magicMemPrefixes[k] + magicMemFuncNames[i];
+                w = M.getFunction(wName);
+                if(w) {
+                    wName2 = wName + "_";
+                    break;
+                }
+            }
+            if(!w) {
+                magicPassErr("Error: no wrapper function found for " << magicMemFuncNames[i] << "()");
+                exit(1);
+            }
+            while(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType()) && (w2 = M.getFunction(wName2))) {
+                w = w2;
+                wName2.append("_");
+            }
+            if(!isCompatibleMagicMemFuncType(f->getFunctionType(), w->getFunctionType())) {
+                magicPassErr("Error: wrapper function with incompatible type " << wName << "() found");
+                magicPassErr(TypeUtil::getDescription(f->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(w->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+                exit(1);
+            }
+            bool isDeallocFunction = false;
+            for(unsigned j=0;magicMemDeallocFuncNames[j].compare("");j++) {
+                if(!magicMemDeallocFuncNames[j].compare(magicMemFuncNames[i])) {
+                    isDeallocFunction = true;
+                    break;
+                }
+            }
+            MagicMemFunction memFunction(M, f, w, isDeallocFunction, allocFlags);
+            magicMemFunctions.push_back(memFunction);
+            originalMagicMemFunctions.insert(f);
+
+#if DEBUG_ALLOC_LEVEL >= 1
+            magicPassErr("Memory management function/wrapper found: " << f->getName() << "()/" << w->getName() << "()");
+#endif
+        }
+    }
+
+    //look up custom memory management functions and build the corresponding wrappers
+    int stdAllocFlags = 0;
+    Function *stdAllocFunc, *stdAllocWrapperFunc;
+    stdAllocFunc = M.getFunction(MAGIC_MALLOC_FUNC_NAME);
+    assert(stdAllocFunc && "Could not find the standard allocation function.");
+    for(i=0;magicMemFuncNames[i].compare("");i++) {
+       if (!magicMemFuncNames[i].compare(MAGIC_MALLOC_FUNC_NAME)) {
+               stdAllocFlags = magicMemFuncAllocFlags[i];
+               break;
+       }
+    }
+    assert(magicMemFuncNames[i].compare("") && "Could not find the flags for the standard allocation function.");
+    std::string wName;
+    for(i=0;magicMemPrefixes[i].compare("");i++) {
+       wName = magicMemPrefixes[i] + MAGIC_MALLOC_FUNC_NAME;
+       stdAllocWrapperFunc = M.getFunction(wName);
+       if (stdAllocWrapperFunc) {
+               break;
+       }
+    }
+    assert(stdAllocWrapperFunc && "Could not find a wrapper for the standard allocation function.");
+    for (std::set<std::pair<std::string, std::string> >::iterator it = mmFuncPairs.begin(); it != mmFuncPairs.end(); ++it) {
+       std::vector<std::string> allocTokens;
+       PassUtil::parseStringListOpt(allocTokens, (*it).first, "/");
+               assert((allocTokens.size() == stdAllocFunc->getFunctionType()->getNumParams() + 1) && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
+
+               // build custom wrapper for the allocation function
+               Function *allocFunction = MagicUtil::getFunction(M, allocTokens[0]);
+               if (!allocFunction) {
+                       continue;
+               }
+               std::vector<unsigned> allocArgMapping;
+               int param;
+               for (unsigned i = 0; i < stdAllocFunc->getFunctionType()->getNumParams(); i++) {
+                       int ret = StringRef(allocTokens[i + 1]).getAsInteger(10, param);
+                       assert(!ret && "Bad option format, format is: customFuncName/stdFuncArg1Mapping/.../stdFuncArgNMapping");
+                       assert(param > 0 && "The numbering of function parameters starts from 1.");
+                       allocArgMapping.push_back(param);
+               }
+               FunctionType *allocFuncType = getFunctionType(allocFunction->getFunctionType(), allocArgMapping);
+               if(!isCompatibleMagicMemFuncType(allocFuncType, stdAllocWrapperFunc->getFunctionType())) {
+                       magicPassErr("Error: standard wrapper function " << stdAllocWrapperFunc->getName() << " has incompatible type.");
+                       magicPassErr(TypeUtil::getDescription(allocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(stdAllocWrapperFunc->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+                       exit(1);
+               }
+               Function *allocWrapper = MagicMemFunction::getCustomWrapper(allocFunction, stdAllocFunc, stdAllocWrapperFunc, allocArgMapping, false);
+
+               // register the wrapper
+               MagicMemFunction memFunctionAlloc(M, allocFunction, allocWrapper, false, stdAllocFlags);
+               magicMemFunctions.push_back(memFunctionAlloc);
+               originalMagicMemFunctions.insert(allocFunction);
+#if DEBUG_ALLOC_LEVEL >= 1
+        magicPassErr("Allocation function/custom wrapper added: " << allocFunction->getName() << "()/" << allocWrapper->getName() << "()");
+#endif
+    }
+
+    //lookup memory pool management functions and add the corresponding wrapper calls
+    int mempoolAllocFlags = MAGIC_STATE_HEAP;
+       Function *mempoolBlockAllocTemplate, *mempoolBlockAllocTemplateWrapper;
+       mempoolBlockAllocTemplate = MagicUtil::getFunction(M,  MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME);
+       assert(mempoolBlockAllocTemplate && "Could not find the pool block allocation template function.");
+       for(i = 0; magicMemPrefixes[i].compare(""); i++) {
+               wName = magicMemPrefixes[i] + MAGIC_MEMPOOL_BLOCK_ALLOC_TEMPLATE_FUNC_NAME;
+               mempoolBlockAllocTemplateWrapper = MagicUtil::getFunction(M, wName);
+               if (mempoolBlockAllocTemplateWrapper) {
+                       break;
+               }
+       }
+       assert(mempoolBlockAllocTemplateWrapper && "Could not find a wrapper for the pool block allocation template function.");
+#define __X(P) #P
+       // C++11 Initializer Lists are not yet supported as of Clang 3.0 ...
+    std::pair<std::string, std::string> magicMempoolFuncNames[] = {
+               std::pair<std::string, std::string>(MAGIC_MEMPOOL_CREATE_FUNCS),
+               std::pair<std::string, std::string>(MAGIC_MEMPOOL_DESTROY_FUNCS),
+               std::pair<std::string, std::string>(MAGIC_MEMPOOL_MGMT_FUNCS),
+               std::pair<std::string, std::string>(MAGIC_MEMPOOL_RESET_FUNCS)
+    };
+#undef __X
+    int magicMempoolFuncFlags[] = { MAGIC_MEMPOOL_FUNC_FLAGS };
+    unsigned numMagicMempoolFuncPairs = sizeof(magicMempoolFuncNames) / sizeof(magicMempoolFuncNames[0]);
+    std::vector<std::pair<Function*, Function*> > magicMempoolFuncs(numMagicMempoolFuncPairs, std::pair<Function*, Function*>());
+    for (i = 0; i < numMagicMempoolFuncPairs; i++) {
+       magicMempoolFuncs[i].first = MagicUtil::getFunction(M, magicMempoolFuncNames[i].first);
+       if (!magicMempoolFuncs[i].first) {
+                       magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].first);
+                       exit(1);
+               }
+       magicMempoolFuncs[i].second = MagicUtil::getFunction(M, magicMempoolFuncNames[i].second);
+       if (!magicMempoolFuncs[i].second) {
+                       magicPassErr("Could not find one of the memory pool wrapper functions: " + magicMempoolFuncNames[i].second);
+                       exit(1);
+               }
+    }
+
+    std::vector<MagicDebugFunction> magicDebugFunctions;
+    if (mmPoolFunctions.size()) {
+               assert(mmPoolFunctions.size() >= 3 && mmPoolFunctions.size() <= 5 &&
+                                               "Specify at least 3 and at most 5 of the pool management types of functions: block alloc,pool create,pool destroy,pool management functions,pool reset functions.");
+               std::vector<std::string>::iterator mmPoolFuncsIt = mmPoolFunctions.begin();
+               std::vector<MagicMemFunction> mempoolMagicMemFunctions;
+
+               // memory pool block allocation functions
+               std::vector<std::string> mempoolBlockAllocFuncs;
+               PassUtil::parseStringListOpt(mempoolBlockAllocFuncs, *(mmPoolFuncsIt++), ";");
+
+               for (std::vector<std::string>::iterator funcIt = mempoolBlockAllocFuncs.begin(); funcIt != mempoolBlockAllocFuncs.end(); ++funcIt) {
+                       std::vector<std::string> funcTokens;
+                       PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
+                       assert(funcTokens.size() == 3 && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
+                       Function* blockAllocFunc = MagicUtil::getFunction(M, funcTokens[0]);
+                       if (!blockAllocFunc) {
+                           magicPassErr("Memory pool block allocation function not found - " + funcTokens[0] + ". Skipping instrumentation!");
+                           mempoolMagicMemFunctions.clear();
+                           break;
+                       }
+                       std::vector<unsigned> argMapping;
+                       unsigned param;
+                       for (unsigned i = 1; i < funcTokens.size(); i++) {
+                               assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: block_alloc_func/pool_ptr_arg_number/size_arg_number");
+                               assert(param > 0 && param <= blockAllocFunc->getFunctionType()->getNumParams()
+                                               && "Bad option format. The function parameter number is not valid.");
+                               argMapping.push_back(param);
+                       }
+                       FunctionType *blockAllocFuncType = getFunctionType(mempoolBlockAllocTemplate->getFunctionType(), argMapping);
+                       if(!isCompatibleMagicMemFuncType(blockAllocFuncType, mempoolBlockAllocTemplateWrapper->getFunctionType())) {
+                               magicPassErr("Error: standard wrapper function " << mempoolBlockAllocTemplateWrapper->getName() << " has incompatible type.");
+                               magicPassErr(TypeUtil::getDescription(blockAllocFuncType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << " != " << TypeUtil::getDescription(mempoolBlockAllocTemplateWrapper->getFunctionType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+                               exit(1);
+                       }
+                       Function *blockAllocWrapper = MagicMemFunction::getCustomWrapper(blockAllocFunc, mempoolBlockAllocTemplate, mempoolBlockAllocTemplateWrapper, argMapping, false);
+                       MagicMemFunction memFunctionBlockAlloc(M, blockAllocFunc, blockAllocWrapper, false, mempoolAllocFlags);
+                       mempoolMagicMemFunctions.push_back(memFunctionBlockAlloc);
+               }
+               if (!mempoolMagicMemFunctions.empty()) { // only if the block allocation functions have been successfully processed
+                       // continue with the rest of the memory pool management functions, which do not require a magic wrapper
+                       std::vector<std::vector<Function*> >::iterator magicMempoolFuncIt;
+                       std::vector<std::vector<int> >::iterator magicMempoolFuncFlagsIt;
+                       for (unsigned magicMempoolFuncIndex = 1; mmPoolFuncsIt != mmPoolFunctions.end(); ++mmPoolFuncsIt, ++magicMempoolFuncIndex) {
+                               std::vector<std::string> mempoolMgmtFuncs;
+                               PassUtil::parseStringListOpt(mempoolMgmtFuncs, *mmPoolFuncsIt, ";");
+                               for (std::vector<std::string>::iterator funcIt = mempoolMgmtFuncs.begin(); funcIt != mempoolMgmtFuncs.end(); ++funcIt) {
+                                       std::vector<std::string> funcTokens;
+                                       PassUtil::parseStringListOpt(funcTokens, *funcIt, "/");
+                                       assert(funcTokens.size() == 2 && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
+                                       Function* mempoolMgmtFunc = MagicUtil::getFunction(M, funcTokens[0]);
+                                       assert(mempoolMgmtFunc && "Bad memory pool configuration, instrumentation aborted!");
+                                       std::vector<unsigned> argMapping;
+                                       unsigned param;
+                                       for (unsigned i = 1; i < funcTokens.size(); i++) {
+                                               assert(!StringRef(funcTokens[i]).getAsInteger(10, param) && "Bad option format, format is: mempool_mgmt_func/pool_ptr_arg_number");
+                                               assert(param <= mempoolMgmtFunc->getFunctionType()->getNumParams() &&
+                                                               "Bad option format. The function parameter number is not valid.");
+                                               argMapping.push_back(param);
+                                       }
+                                       std::vector<Value*> trailingArgs;
+                                       if (magicMempoolFuncIndex == 1) { // pool create funcs
+                                               TYPECONST Type* poolType = mempoolMgmtFunc->getFunctionType()->getContainedType(argMapping[0]);
+                                               int level = MagicUtil::getPointerIndirectionLevel(poolType);
+                                               trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (level > 1)));
+                                       } else if (magicMempoolFuncIndex == 2) { // pool destroy funcs
+                                               trailingArgs.push_back(ConstantInt::get(Type::getInt32Ty(M.getContext()), (EnablePoolMemReuse ? 1 : 0)));
+                                       }
+                                       if (magicMempoolFuncFlags[magicMempoolFuncIndex - 1] & MAGIC_HOOK_DEBUG_MASK) {
+                                               MagicDebugFunction magicDebugFunction(mempoolMgmtFunc);
+                                               magicDebugFunction.addHooks(magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
+                                               magicDebugFunctions.push_back(magicDebugFunction);
+                                       } else {
+                                               bool ret = MagicDebugFunction::inlineHookCalls(mempoolMgmtFunc,
+                                                               magicMempoolFuncs[magicMempoolFuncIndex - 1], magicMempoolFuncFlags[magicMempoolFuncIndex - 1], argMapping, trailingArgs);
+                                               if (!ret) {
+                                                       magicPassErr("Unable to inline wrapper function calls for " + funcTokens[0]);
+                                                       exit(1);
+                                               }
+                                       }
+                               }
+                       }
+                       for (std::vector<MagicMemFunction>::iterator magicIt = mempoolMagicMemFunctions.begin(); magicIt != mempoolMagicMemFunctions.end(); ++magicIt) {
+                               magicMemFunctions.push_back(*magicIt);
+                               originalMagicMemFunctions.insert(magicIt->getFunction());
+                       }
+               }
+    }
+
+    //lookup mmap ctl functions whose call arguments need to be fixed
+    std::vector<MagicMmapCtlFunction> magicMmapCtlFunctions;
+    for (std::vector<std::string>::iterator it = mmapCtlFunctions.begin(); it != mmapCtlFunctions.end(); ++it) {
+        std::vector<std::string> tokens;
+        tokens.clear();
+        PassUtil::parseStringListOpt(tokens, *it, "/");
+        assert(tokens.size() == 3 && "Bad option format, format is: function/[ptr_arg_name]/[len_arg_name]");
+
+        Function *function = M.getFunction(tokens[0]);
+        if(!function) {
+            continue;
+        }
+        std::string &ptrArgName = tokens[1];
+        std::string &lenArgName = tokens[2];
+        MagicMmapCtlFunction magicMmapCtlFunction(function, PointerType::get(IntegerType::get(M.getContext(), 8), 0), ptrArgName, lenArgName);
+        magicMmapCtlFunctions.push_back(magicMmapCtlFunction);
+    }
+#endif
+
+    //everything as expected, set magic enabled variable to TRUE
+    magicEnabled->setInitializer(ConstantInt::get(M.getContext(), APInt(32, 1)));
+
+    //scan the list of global variables
+    unsigned strGlobalVariables = 0;
+    unsigned constGlobalVariables = 0;
+    for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+        GlobalVariable *GV = it;
+        StringRef GVName = GV->getName();
+        TYPECONST Type *GVType = GV->getType()->getElementType();
+        bool isPrimitiveOrPointerType = !GVType->isAggregateType();
+        DATA_LAYOUT_TY DL = DATA_LAYOUT_TY(&M);
+        bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
+        int typeSize = isExternal ? 0 : DL.getTypeSizeInBits(GVType)/8;
+        int align = MAGIC_FORCE_ALIGN;
+
+        if(isMagicGV(M, GV)) {
+            magicPassLog("Skipping magic variable: " << GVName);
+            continue;
+        }
+        assert(!MAGIC_STRINGREF_HAS_MAGIC_HIDDEN_PREFIX(GVName));
+        if(GVName.startswith("C.")) {
+            //LLVM code we are not interested in
+            continue;
+        }
+        if(MagicUtil::isLocalConstant(M, GV)) {
+            //Local constants we are not interested in
+            continue;
+        }
+#if GLOBAL_VARS_IN_SECTION
+        MagicUtil::setGlobalVariableSection(GV, GV->isConstant() ? GLOBAL_VARS_SECTION_RO : GLOBAL_VARS_SECTION_DATA);
+#endif
+        if(GVName.startswith(".str")) {
+            assert(GV->hasInitializer());
+#if LLVM_VERSION >= 31
+            /* XXX Check. */
+            ConstantDataArray *initializer = dyn_cast<ConstantDataArray>(GV->getInitializer());
+#else
+            ConstantArray *initializer = dyn_cast<ConstantArray>(GV->getInitializer());
+#endif
+            if(initializer) {
+                assert(initializer->isString());
+                MagicUtil::putStringRefCache(M, initializer->getAsString(), GV);
+            }
+            else {
+                MagicUtil::putStringRefCache(M, "", GV);
+            }
+
+            strGlobalVariables++;
+            Value *stringOwner = MagicUtil::getStringOwner(GV);
+            if(stringOwner) {
+                GlobalVariable *GVOwner = dyn_cast<GlobalVariable>(stringOwner);
+                AllocaInst *AIOwner = dyn_cast<AllocaInst>(stringOwner);
+                assert(GVOwner || AIOwner);
+                bool stringOwnerFound = false;
+                std::string ownerName;
+                raw_string_ostream ostream(ownerName);
+                if(GVOwner && !isMagicGV(M, GVOwner)) {
+                    ostream << "#" << MagicUtil::getGVSourceName(M, GVOwner, NULL, baseBuildDir);
+                    stringOwnerFound = true;
+                }
+                else if(AIOwner && !isMagicFunction(M, AIOwner->getParent()->getParent())) {
+                    ostream << MagicUtil::getFunctionSourceName(M, AIOwner->getParent()->getParent(), NULL, baseBuildDir) << "#" << MagicUtil::getLVSourceName(M, AIOwner);
+                    stringOwnerFound = true;
+                }
+                if(stringOwnerFound) {
+                    ostream.flush();
+                    stringOwnerMapIt = stringOwnerMap.find(ownerName);
+                    if(stringOwnerMapIt == stringOwnerMap.end()) {
+                        stringOwnerMap.insert(std::pair<std::string, GlobalVariable*>(ownerName, GV));
+                        stringOwnerInvertedMap.insert(std::pair<GlobalVariable*, std::string>(GV, ownerName));
+                    }
+                    else {
+                        stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(stringOwnerMapIt->second);
+                        if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
+                            stringOwnerInvertedMap.erase(stringOwnerInvertedMapIt);
+                        }
+                    }
+                }
+            }
+        }
+        else if(GV->isConstant()) {
+            constGlobalVariables++;
+        }
+        if(!isPrimitiveOrPointerType && align) {
+            GV->setAlignment(align);
+            if(typeSize % align) {
+                typeSize = typeSize - (typeSize % align) + align;
+            }
+        }
+        else if(MAGIC_OFF_BY_N_PROTECTION_N && GVType->isArrayTy() && typeSize>0) {
+            unsigned alignment = typeSize + (DL.getTypeSizeInBits(GVType->getContainedType(0))/8) * MAGIC_OFF_BY_N_PROTECTION_N;
+            unsigned a = 2;
+            while(a < alignment) a = a << 1;
+            GV->setAlignment(a);
+        }
+        globalVariableSizes.push_back(typeSize);
+        globalVariables.push_back(GV);
+        if(MagicUtil::hasAddressTaken(GV)) {
+            globalVariablesWithAddressTaken.insert(GV);
+        }
+    }
+    magicPassLog(">>>> Number of global variables found: " << globalVariables.size() << " of which " << strGlobalVariables << " .str variables, " << constGlobalVariables << " constants, and " << globalVariables.size()-strGlobalVariables-constGlobalVariables << " regular variables");
+
+    //build the list of functions having their address taken (include the last function no matter what to get the function ranges right)
+    std::vector<const SmartType *> functionTypes;
+    std::vector<GlobalValue *> functionTypeParents;
+    std::vector<TYPECONST FunctionType *> externalFunctionTypes;
+    std::vector<GlobalValue *> externalFunctionTypeParents;
+    for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
+        Function *F = it;
+        if(F->hasAddressTaken() || it == --functionList.end() || F->getName().startswith(MAGIC_EVAL_FUNC_PREFIX)) {
+            if(isMagicFunction(M, F)) {
+                continue;
+            }
+            functions.push_back(F);
+            const SmartType *FSmartType = SmartType::getSmartTypeFromFunction(M, F);
+            if(FSmartType && !FSmartType->isTypeConsistent()) {
+                delete FSmartType;
+                //pretend the function is external if an invalid type has been found.
+                FSmartType = NULL;
+            }
+            if(!FSmartType) {
+                externalFunctionTypes.push_back(F->getFunctionType());
+                externalFunctionTypeParents.push_back(F);
+            }
+            else {
+                functionTypes.push_back(FSmartType);
+                functionTypeParents.push_back(F);
+            }
+        }
+    }
+    magicPassLog(">>>> Number of functions with address taken found: " << functions.size() << ", of which " << functionTypes.size() << " internal and " << externalFunctionTypes.size() << " external...");
+
+    //build the list of global types
+    std::vector<const SmartType *> smartTypes;
+    std::vector<GlobalValue *> smartTypeParents;
+    std::vector<TYPECONST Type *> externalTypes;
+    std::vector<GlobalValue *> externalTypeParents;
+    for(i=0;i<globalVariables.size();i++) {
+        GlobalVariable *GV = globalVariables[i];
+        TYPECONST Type* GVType = GV->getType()->getElementType();
+
+        const SmartType *GVSmartType = SmartType::getSmartTypeFromGV(M, GV);
+
+        if(!GV->hasAppendingLinkage()){
+            // llvm.global_ctors and llvm.global_dtors have appending linkage, don't have compile unit debug info, and therefore cannot be linked to GV debug info, and so are skipped.
+            if(!GVSmartType) {
+               bool isExternal = GV->hasExternalLinkage() || GV->hasExternalWeakLinkage();
+                if (!isExternal && !GV->isConstant()) {
+                    magicPassErr("var is: " << GV->getName());
+                    magicPassErr("type is: " << TypeUtil::getDescription(GV->getType()->getElementType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+               }
+                assert(isExternal || GV->isConstant());
+                externalTypes.push_back(GVType);
+                externalTypeParents.push_back(GV);
+            }
+            else {
+                smartTypes.push_back(GVSmartType);
+                smartTypeParents.push_back(GV);
+            }
+        }
+    }
+    magicPassLog(">>>> Number of global types found: " << globalVariables.size() << ", of which " << smartTypes.size() << " internal and " << externalTypes.size() << " external...");
+
+    //build type infos
+    TypeInfo* magicVoidPtrTypeInfo = NULL;
+    TypeInfo* magicVoidArrTypeInfo = NULL;
+    TypeInfo* magicVoidTypeInfo = NULL;
+    for(i=0;i<smartTypes.size();i++) {
+        TypeInfo sourceTypeInfo(smartTypes[i]);
+        sourceTypeInfo.addParent(smartTypeParents[i]);
+        TypeInfo *aTypeInfo = fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+        if(smartTypeParents[i] == magicVoidPtr) {
+            //get a pointer to void and void* types
+            magicVoidPtrTypeInfo = aTypeInfo;
+            assert(magicVoidPtrTypeInfo->getTypeID() == MAGIC_TYPE_POINTER);
+            magicVoidTypeInfo = magicVoidPtrTypeInfo->getContainedType(0);
+            assert(magicVoidTypeInfo->getTypeID() == MAGIC_TYPE_VOID);
+        }
+        else if(smartTypeParents[i] == magicVoidArr) {
+            //get a pointer to void array types
+            magicVoidArrTypeInfo = aTypeInfo;
+            assert(magicVoidArrTypeInfo->getTypeID() == MAGIC_TYPE_ARRAY);
+        }
+    }
+    assert(magicVoidPtrTypeInfo && magicVoidTypeInfo && magicVoidArrTypeInfo);
+    std::vector<TypeInfo*> magicVoidTypeInfoArr;
+    magicVoidTypeInfoArr.push_back(magicVoidTypeInfo);
+    magicVoidArrTypeInfo->setContainedTypes(magicVoidTypeInfoArr);
+    magicPassLog(">>>> Number of types found: " << globalTypeInfos.size());
+    for(i=0;i<functionTypes.size();i++) {
+        TypeInfo sourceTypeInfo(functionTypes[i]);
+        sourceTypeInfo.addParent(functionTypeParents[i]);
+        fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+    }
+    magicPassLog(">>>> Number of types + function types found: " << globalTypeInfos.size());
+
+    //add external function types
+    for(i=0;i<externalFunctionTypes.size();i++) {
+        TypeInfo sourceTypeInfo(externalFunctionTypes[i]);
+        sourceTypeInfo.addParent(externalFunctionTypeParents[i]);
+        fillTypeInfos(sourceTypeInfo, globalTypeInfos);
+    }
+    magicPassLog(">>>> Number of types + function types + external function types found: " << globalTypeInfos.size());
+
+    //add external variable types
+    for(i=0;i<externalTypes.size();i++) {
+        TypeInfo* aTypeInfo = fillExternalTypeInfos(externalTypes[i], externalTypeParents[i], globalTypeInfos);
+        if(aTypeInfo == NULL) {
+            magicPassErr("var is: " << externalTypeParents[i]->getName());
+            magicPassErr("type is: " << TypeUtil::getDescription(externalTypes[i], MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+        }
+        assert(aTypeInfo != NULL && "External type not supported!");
+    }
+    magicPassLog(">>>> Number of types + external types + function types + external function types found: " << globalTypeInfos.size());
+
+    //process types, split them when some parent has a valid value set
+    std::vector<TypeInfo*> splitTypeInfos;
+    for(i=0;i<globalTypeInfos.size();i++) {
+        bool isTypeInfoSplit = globalTypeInfos[i]->splitByParentValueSet(splitTypeInfos, globalVariablesWithAddressTaken);
+        if(isTypeInfoSplit) {
+#if DEBUG_VALUE_SET
+            unsigned splitTypeInfosSize = splitTypeInfos.size();
+            errs() << "MagicPass: Found type info split with different parents and value sets: original type is: " << globalTypeInfos[i]->getDescription() << ", type splits are:\n";
+            for(unsigned j=splitTypeInfosSize;j<splitTypeInfos.size();j++) {
+                errs() << " - value set is: [ ";
+                std::vector<int> valueSet = splitTypeInfos[j]->getValueSet();
+                for(unsigned k=1;k<valueSet.size();k++) {
+                    errs() << (k==1 ? "" : ", ") << valueSet[k];
+                }
+                errs() << " ], parents are: [ ";
+                std::vector<GlobalValue*> parents = splitTypeInfos[j]->getParents();
+                for(unsigned k=0;k<parents.size();k++) {
+                    errs() << (k==0 ? "" : ", ") << parents[k]->getName();
+                }
+                errs() << " ]\n";
+            }
+#endif
+        }
+    }
+
+    //index type parents
+    globalTypeInfos.clear();
+    for(i=0;i<splitTypeInfos.size();i++) {
+        TypeInfo *aTypeInfo = splitTypeInfos[i];
+        std::vector<GlobalValue*> parents = aTypeInfo->getParents();
+        for(unsigned j=0;j<parents.size();j++) {
+            parentMapIt = globalParentMap.find(parents[j]);
+            assert(parentMapIt == globalParentMap.end());
+            globalParentMap.insert(std::pair<GlobalValue*, TypeInfo*>(parents[j], aTypeInfo));
+        }
+        globalTypeInfos.push_back(aTypeInfo);
+    }
+
+    std::vector< TypeInfo* > magicDsindexTypeInfoList;
+    std::vector< std::pair<std::string,std::string> > magicDsindexNamesList;
+    std::vector<int> magicDsindexFlagsList;
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+    //gather magic memory function calls to replace and figure out the type (adding more (local) types if needed)
+    std::vector<MagicMemFunction> magicMemFunctionCalls;
+    std::map< std::pair<std::string,std::string>, int> namesMap;
+    int allocFlags;
+    std::set<Function*> extendedMagicMemFunctions;
+    for (std::set<Function*>::iterator it = originalMagicMemFunctions.begin(); it != originalMagicMemFunctions.end(); ++it) {
+        PassUtil::getFunctionsInDirectBUCallgraph(*it, extendedMagicMemFunctions);
+    }
+    while(!magicMemFunctions.empty()) {
+        MagicMemFunction magicMemFunction = magicMemFunctions.front();
+        magicMemFunctions.erase(magicMemFunctions.begin());
+        std::vector<User*> Users(magicMemFunction.getFunction()->use_begin(), magicMemFunction.getFunction()->use_end());
+        std::vector<Value*> EqPointers;
+        while (!Users.empty()) {
+          int annotation;
+          User *U = Users.back();
+          Users.pop_back();
+        
+          if (Instruction *I = dyn_cast<Instruction>(U)) {
+            Function *parent = I->getParent()->getParent();
+            if (isMagicFunction(M, parent) || MagicMemFunction::isCustomWrapper(parent)) {
+                continue;
+            }
+            CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
+            if (CS.getInstruction() &&
+                (!CS.arg_empty() || magicMemFunction.getWrapper() == NULL) &&
+                (MagicUtil::getCalledFunctionFromCS(CS) == magicMemFunction.getFunction() ||
+                 std::find(EqPointers.begin(), EqPointers.end(),
+                           CS.getCalledValue()) != EqPointers.end())) {
+              bool isDeallocFunction = magicMemFunction.isDeallocFunction();
+              bool wrapParent = false;
+              TypeInfo *typeInfo = magicVoidTypeInfo;
+              std::string allocName = "";
+              std::string allocParentName = "";
+              //check if we have to skip
+              if(extendedMagicMemFunctions.find(CS.getInstruction()->getParent()->getParent()) != extendedMagicMemFunctions.end()) {
+                  //this call site is only called from some predefined mem function. skip.
+                  continue;
+              }
+              if(sbrkFunctions.find(MagicUtil::getCalledFunctionFromCS(CS)) != sbrkFunctions.end()) {
+                  ConstantInt *arg = dyn_cast<ConstantInt>(CS.getArgument(0));
+                  if(arg && arg->getZExtValue() == 0) {
+                      //ignore sbrk(0) calls. This does not skip calls with a variable argument (when arg == NULL)
+#if DEBUG_ALLOC_LEVEL >= 1
+                      magicPassErr("Skipping instrumentation of sbrk(0) MM call found in " << parent->getName() << "():");
+                      I->print(errs());
+                      errs() << "\n";
+#endif
+                      continue;
+                  }
+              }
+              else if(MagicUtil::getCallAnnotation(M, CS, &annotation)
+                  && annotation == MAGIC_CALL_MEM_SKIP_INSTRUMENTATION) {
+                  //ignore calls we are supposed to skip
+#if DEBUG_ALLOC_LEVEL >= 1
+                  magicPassErr("Skipping instrumentation of annotated MM call found in " << parent->getName() << "():");
+                  I->print(errs());
+                  errs() << "\n";
+#endif
+                  continue;
+              }
+              //figure out the type and the names
+              if(!isDeallocFunction) {
+                 int allocCounter = 1;
+                 int ret;
+                 std::map< std::pair<std::string,std::string>, int>::iterator namesMapIt;
+                 //get alloc types and names
+                 TypeInfo *allocTypeInfo = getAllocTypeInfo(M, magicVoidPtrTypeInfo, CS, allocName, allocParentName);
+#if !MAGIC_INSTRUMENT_MEM_CUSTOM_WRAPPERS
+                  if(!allocTypeInfo) {
+                      allocTypeInfo = voidTypeInfo;
+                  }
+#endif
+                  if(allocTypeInfo) {
+                      typeInfo = allocTypeInfo;
+                  }
+                  else {
+                      int pointerParam = MagicMemFunction::getMemFunctionPointerParam(I->getParent()->getParent(), brkFunctions, magicVoidPtrTypeInfo);
+                      if(pointerParam >= 0 /* && !I->getParent()->getParent()->hasAddressTaken() */) {
+                          //the parent is a valid magic mem function to wrap
+                          wrapParent = true;
+                      }
+                  }
+                  if(!wrapParent) {
+                      assert(allocParentName.compare("") && "Empty parent name!");
+                      if(!allocName.compare("")) {
+                         allocName = MAGIC_ALLOC_NONAME;
+                      }
+
+#if (MAGIC_NAMED_ALLOC_USE_DBG_INFO || (MAGIC_MEM_USAGE_OUTPUT_CTL == 1))
+                      //extend names with debug information when requested
+                      if (MDNode *N = I->getMetadata("dbg")) {
+                         DILocation Loc(N);
+                         std::string string;
+                         raw_string_ostream ostream(string);
+                         ostream << allocName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
+                         ostream.flush();
+                         allocName = string;
+                      }
+#endif
+
+#if MAGIC_FORCE_ALLOC_EXT_NAMES
+                      if (isExtLibrary(parent, NULL)) {
+                         allocName = MAGIC_ALLOC_EXT_NAME;
+                         allocName = MAGIC_ALLOC_EXT_PARENT_NAME;
+                      }
+#endif
+
+                      //avoid duplicates
+                     namesMapIt = namesMap.find(std::pair<std::string, std::string>(allocParentName, allocName));
+                     if(namesMapIt != namesMap.end()) {
+                         allocCounter = namesMapIt->second + 1;
+                        ret = namesMap.erase(std::pair<std::string, std::string>(allocParentName, allocName));
+                        assert(ret == 1);
+                         namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
+                         std::string string;
+                         raw_string_ostream ostream(string);
+                         ostream << allocName << MAGIC_ALLOC_NAME_SUFFIX << allocCounter;
+                         ostream.flush();
+                         allocName = string;
+                     }
+                     else {
+                        namesMap.insert(std::pair<std::pair<std::string, std::string>, int>(std::pair<std::string, std::string>(allocParentName, allocName), allocCounter));
+                         allocName += MAGIC_ALLOC_NAME_SUFFIX;
+                     }
+                     magicMemFunction.setInstructionTypeInfo(typeInfo, allocName, allocParentName);
+                      //add dsindex entries
+                      magicDsindexTypeInfoList.push_back(typeInfo);
+                      magicDsindexNamesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
+                      allocFlags = magicMemFunction.getAllocFlags();
+                      assert(allocFlags);
+                      magicDsindexFlagsList.push_back(allocFlags);
+                  }
+              }
+              magicMemFunction.setInstruction(I);
+              Function *instructionParent = I->getParent()->getParent();
+              //see if we can find the parent in our lists
+              MagicMemFunction *magicMemParent = NULL;
+              for(unsigned k=0;k<magicMemFunctions.size();k++) {
+                  if(magicMemFunctions[k].getFunction() == instructionParent) {
+                      magicMemParent = &magicMemFunctions[k];
+                      break;
+                  }
+              }
+              if(!magicMemParent) {
+                  for(unsigned k=0;k<magicMemFunctionCalls.size();k++) {
+                      if(magicMemFunctionCalls[k].getFunction() == instructionParent) {
+                          magicMemParent = &magicMemFunctionCalls[k];
+                          break;
+                      }
+                  }
+              }
+              if(!magicMemParent && wrapParent) {
+                  //if there is no existing parent but we have to wrap the parent, create a parent now and add it to the function queue
+                  MagicMemFunction newMagicMemFunction(M, instructionParent, NULL, false, 0);
+                  magicMemFunctions.push_back(newMagicMemFunction);
+                  magicMemParent = &magicMemFunctions[magicMemFunctions.size()-1];
+              }
+              if(magicMemParent) {
+                  //if we have a parent, add a dependency
+                  magicMemParent->addInstructionDep(magicMemFunction);
+                  assert(magicMemParent->getAllocFlags());
+
+              }
+              else {
+                  //if there is no parent, add it to the call queue
+                  magicMemFunctionCalls.push_back(magicMemFunction);
+              }
+            }
+          } 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);
+            }
+          }
+        }
+    }
+#endif
+
+#if MAGIC_INSTRUMENT_STACK
+    std::vector<std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > > localTypeInfoMaps;
+    std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > localTypeInfoMap;
+    std::vector<Function*> stackIntrumentedFuncs;
+    fillStackInstrumentedFunctions(stackIntrumentedFuncs, deepestLLFunction);
+    std::string stackIntrumentedFuncsStr;
+    for(i=0;i<stackIntrumentedFuncs.size();i++) {
+        localTypeInfoMap.clear();
+        indexLocalTypeInfos(M, stackIntrumentedFuncs[i], localTypeInfoMap);
+        localTypeInfoMaps.push_back(localTypeInfoMap);
+        stackIntrumentedFuncsStr += (i==0 ? "" : ", ") + stackIntrumentedFuncs[i]->getName().str() + "()";
+    }
+    magicPassLog(">>>> Set of stack-instrumented functions expanded from function " << deepestLLFunction->getName() << "(): " << stackIntrumentedFuncsStr);
+    magicPassLog(">>>> Number of types + external types + function types + external function types + local types found: " << globalTypeInfos.size());
+#endif
+
+    //add raw types
+    std::vector<TypeInfo*> rawTypeInfos;
+    for(i=0;i<globalTypeInfos.size();i++) {
+        TypeInfo* aTypeInfo = globalTypeInfos[i];
+        if(!aTypeInfo->hasRawTypeRepresentation()) {
+            continue;
+        }
+        assert(aTypeInfo->getNumContainedTypes() == 0);
+        TypeInfo* aRawTypeInfo = new TypeInfo(*magicVoidArrTypeInfo);
+        aRawTypeInfo->setPersistent();
+        aRawTypeInfo->removeAllParents();
+        rawTypeInfos.push_back(aRawTypeInfo);
+        std::vector<TypeInfo*> aTypeInfoContainedTypes;
+        aTypeInfoContainedTypes.push_back(aRawTypeInfo);
+        aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
+        assert(aTypeInfo->getContainedType(0)->getContainedType(0) == magicVoidTypeInfo);
+    }
+    for(i=0;i<rawTypeInfos.size();i++) {
+        globalTypeInfos.push_back(rawTypeInfos[i]);
+        assert(rawTypeInfos[i]->getNumContainedTypes() == 1);
+    }
+    magicPassLog(">>>> Number of types + external types + function types + external function types + local types found + raw types: " << globalTypeInfos.size());
+
+    //find max recursive sequence length
+    unsigned length, maxRecursiveSequenceLength = 0;
+    for(i=0;i<globalTypeInfos.size();i++) {
+        if(globalTypeInfos[i]->getParents().size() > 0) {
+            length = getMaxRecursiveSequenceLength(globalTypeInfos[i]);
+            if(length > maxRecursiveSequenceLength) {
+                maxRecursiveSequenceLength = length;
+            }
+        }
+    }
+    magicPassLog(">>>> Max recursive sequence length: " << maxRecursiveSequenceLength);
+
+    //debug type infos when needed
+#if DEBUG_TYPE_INFOS
+        for(i=0;i<globalTypeInfos.size();i++) {
+            std::vector<GlobalValue*> parents = globalTypeInfos[i]->getParents();
+            if(parents.size() > 0) {
+                std::string parentString, typeString;
+                for(unsigned j=0;j<parents.size();j++) {
+                    parentString.append((j>0 ? ", " : "") + parents[j]->getName().str());
+                }
+                typeString = globalTypeInfos[i]->getDescription();
+                magicPassErr("     Global type group found, parents=( " << parentString << "), type=" << typeString << ", name=" << globalTypeInfos[i]->getName() << ", names_string=" << globalTypeInfos[i]->getNamesString());
+                if(DEBUG_TYPE_INFOS >= 2) {
+                    printInterestingTypes(globalTypeInfos[i]);
+                }
+            }
+        }
+        for(i=0;i<globalTypeInfos.size();i++) {
+            std::string name = globalTypeInfos[i]->getName();
+            if(name.compare("")) {
+                magicPassErr("     Named type found: " << name << " (names string: " << globalTypeInfos[i]->getNamesString() << ", id: " << i << ")");
+            }
+        }
+#endif
+
+#if DEBUG_DUPLICATED_TYPE_INFOS
+    std::map<std::string, TypeInfo*> duplicatedTypeInfoMap;
+    std::map<std::string, TypeInfo*>::iterator duplicatedTypeInfoMapIt;
+    for(i=0;i<globalTypeInfos.size();i++) {
+        if(globalTypeInfos[i]->getType()->isStructTy()) {
+            std::string name = globalTypeInfos[i]->getName();
+            if(!name.compare("")) {
+                continue;
+            }
+            duplicatedTypeInfoMapIt = duplicatedTypeInfoMap.find(name);
+            if(duplicatedTypeInfoMapIt != duplicatedTypeInfoMap.end()) {
+                magicPassErr("Duplicated struct name found: " << name << ": " << globalTypeInfos[i]->getVerboseDescription() << " != " << (duplicatedTypeInfoMapIt->second)->getVerboseDescription());
+            }
+            else {
+                duplicatedTypeInfoMap.insert(std::pair<std::string, TypeInfo*>(name, globalTypeInfos[i]));
+            }
+        }
+    }
+#endif
+
+    //allocate magic type array
+    ArrayType* magicTypeArrayType = ArrayType::get(magicTypeStructType, globalTypeInfos.size());
+    magicTypeArray = new GlobalVariable(M, magicTypeArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicTypeArrayType), MAGIC_TYPE_ARRAY_NAME);
+    MagicUtil::setGlobalVariableSection(magicTypeArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+    //allocate magic array
+    ArrayType* magicArrayType = ArrayType::get(magicStructType, globalVariables.size());
+    magicArray = new GlobalVariable(M, magicArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicArrayType), MAGIC_ARRAY_NAME);
+    MagicUtil::setGlobalVariableSection(magicArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+    //allocate magic function array
+    ArrayType* magicFunctionArrayType = ArrayType::get(magicFunctionStructType, functions.size());
+    magicFunctionArray = new GlobalVariable(M, magicFunctionArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicFunctionArrayType), MAGIC_FUNC_ARRAY_NAME);
+    MagicUtil::setGlobalVariableSection(magicFunctionArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+    //build magic type array in build function
+    i=0;
+    std::map<TypeInfo*, Constant*> magicArrayTypePtrMap;
+    std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
+    std::map<TypeInfo*, unsigned> magicArrayTypeIndexMap;
+    std::map<TypeInfo*, unsigned>::iterator magicArrayTypeIndexMapIt;
+    std::vector<Value*> arrayIndexes;
+    for(;i<globalTypeInfos.size();i++) {
+        TypeInfo* aTypeInfo = globalTypeInfos[i];
+        TYPECONST Type *aType = aTypeInfo->getType();
+        arrayIndexes.clear();
+        arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));     //pointer to A[]
+        arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, i, 10))); //pointer to A[index]
+        Constant* magicTypeArrayPtr = MagicUtil::getGetElementPtrConstant(magicTypeArray, arrayIndexes);
+        magicArrayTypePtrMap.insert(std::pair<TypeInfo*, Constant*>(aTypeInfo, magicTypeArrayPtr));
+        magicArrayTypeIndexMap.insert(std::pair<TypeInfo*, unsigned>(aTypeInfo, i));
+
+        //storing id field
+        Value* structIdField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_ID);
+        Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+        new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+        //storing name field
+        Value* structNameField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAME);
+        Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getName()));
+        new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+        //storing names field
+        std::vector<std::string> names = aTypeInfo->getNames();
+        Value* structNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NAMES);
+        Constant* namesValue;
+        if(names.size() > 0) {
+            namesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, names.size(), &names));
+        }
+        else {
+            namesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structNamesField->getType())->getElementType());
+        }
+        new StoreInst(namesValue, structNamesField, false, magicArrayBuildFuncInst);
+
+        //storing num_names field
+        Value* structNumNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_NAMES);
+        Constant* numNamesValue = ConstantInt::get(M.getContext(), APInt(32, names.size(), 10));
+        new StoreInst(numNamesValue, structNumNamesField, false, magicArrayBuildFuncInst);
+
+        //storing type_str field
+        Value* structTypeStrField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_STR);
+        Constant* typeStrValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, aTypeInfo->getTypeString()));
+        new StoreInst(typeStrValue, structTypeStrField, false, magicArrayBuildFuncInst);
+
+        //filling size field
+        Value* structSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+        Value* typeSizeValue;
+        if(aType->isFunctionTy() || TypeUtil::isOpaqueTy(aType) || aType->isVoidTy()) {
+            typeSizeValue = ConstantInt::get(M.getContext(), APInt(32, 1, 10));
+        }
+        else {
+            assert(aType->isSized());
+            typeSizeValue = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(aType), (TYPECONST IntegerType*)((TYPECONST PointerType*)structSizeField->getType())->getElementType(), true);
+        }
+        new StoreInst(typeSizeValue, structSizeField, false, magicArrayBuildFuncInst);
+
+        //storing num_child_types field
+        Value* structNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
+        Constant* numChildTypesValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getNumChildTypes(), 10));
+        new StoreInst(numChildTypesValue, structNumChildTypesField, false, magicArrayBuildFuncInst);
+
+        //storing member_names field
+        std::vector<std::string> memberNames = aTypeInfo->getMemberNames();
+        Value* structMemberNamesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_NAMES);
+        Constant* memberNamesValue;
+        if(memberNames.size() > 0) {
+            assert(aType->isStructTy());
+            assert(aTypeInfo->getNumContainedTypes() == memberNames.size());
+            memberNamesValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringArrayRef(M, memberNames.size(), &memberNames));
+        }
+        else {
+            memberNamesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberNamesField->getType())->getElementType());
+        }
+        new StoreInst(memberNamesValue, structMemberNamesField, false, magicArrayBuildFuncInst);
+
+        //storing member_offsets field
+        Value* structMemberOffsetsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_MEMBER_OFFSETS);
+        Constant* memberOffsetsValue;
+        if(memberNames.size() > 0) {
+            assert(aType->isStructTy());
+            assert(aTypeInfo->getNumContainedTypes() == aTypeInfo->getNumChildTypes());
+            bool isConstant = false;
+            GlobalVariable *memberOffsetArray = MagicUtil::getIntArrayRef(M, aTypeInfo->getNumChildTypes(), NULL, isConstant);
+            for(unsigned j=0;j<aTypeInfo->getNumChildTypes();j++) {
+                std::vector<Value*> arrayIndexes;
+                arrayIndexes.clear();
+                arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
+                arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, j, 10))); //pointer to A[j]
+                Constant* memberOffsetArrayPtr = MagicUtil::getGetElementPtrConstant(memberOffsetArray, arrayIndexes);
+
+                Value* memberOffsetValue = ConstantExpr::getIntegerCast(ConstantExpr::getOffsetOf((TYPECONST StructType*) aTypeInfo->getType(), j), (TYPECONST IntegerType*)((TYPECONST PointerType*)memberOffsetArrayPtr->getType())->getElementType(), true);
+                new StoreInst(memberOffsetValue, memberOffsetArrayPtr, false, magicArrayBuildFuncInst);
+            }
+            memberOffsetsValue = MagicUtil::getArrayPtr(M, memberOffsetArray);
+        }
+        else {
+            memberOffsetsValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structMemberOffsetsField->getType())->getElementType());
+        }
+        new StoreInst(memberOffsetsValue, structMemberOffsetsField, false, magicArrayBuildFuncInst);
+
+        //storing value set field (for enum values and value set analysis)
+        std::vector<int> valueSet = aTypeInfo->getValueSet();
+        Value* structValueSetField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_VALUE_SET);
+        Constant* valueSetValue;
+        if(valueSet.size() > 0) {
+            valueSetValue = ConstantExpr::getCast(Instruction::BitCast, MagicUtil::getArrayPtr(M, MagicUtil::getIntArrayRef(M, valueSet.size(), &valueSet)), magicVoidPtrTypeInfo->getType());
+        }
+        else {
+            valueSetValue = ConstantPointerNull::get((TYPECONST PointerType*)magicVoidPtrTypeInfo->getType());
+        }
+        new StoreInst(valueSetValue, structValueSetField, false, magicArrayBuildFuncInst);
+        
+        //storing type_id field
+        Value* structTypeIDField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_TYPE_ID);
+        Constant* typeIDValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getTypeID(), 10));
+        new StoreInst(typeIDValue, structTypeIDField, false, magicArrayBuildFuncInst);
+
+        //storing flags field
+        Value* structFlagsField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_FLAGS);
+        Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getFlags(), 10));
+        new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+        //storing bit_width field
+        Value* structBitWidthField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_BIT_WIDTH);
+        Constant* bitWidthValue = ConstantInt::get(M.getContext(), APInt(32, aTypeInfo->getBitWidth(), 10));
+        new StoreInst(bitWidthValue, structBitWidthField, false, magicArrayBuildFuncInst);
+    }
+
+    i=0;
+    //build contained types pointers
+    unsigned dstIndex, voidTypeIndex;
+    magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(magicVoidTypeInfo);
+    assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
+    voidTypeIndex = magicArrayTypeIndexMapIt->second;
+    for(;i<globalTypeInfos.size();i++) {
+        TypeInfo* aTypeInfo = globalTypeInfos[i];
+        std::vector<Constant*> containedTypePtrs;
+        for(unsigned j=0;j<aTypeInfo->getNumContainedTypes();j++) {
+            TypeInfo* containedType = aTypeInfo->getContainedType(j);
+            magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(containedType);
+            assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+
+            containedTypePtrs.push_back(magicArrayTypePtrMapIt->second);
+        }
+        Value* structContainedTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_CONTAINED_TYPES);
+        Constant *containedTypesValue;
+        if(containedTypePtrs.size() > 0) {
+            containedTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, containedTypePtrs));
+        }
+        else {
+            containedTypesValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structContainedTypesField->getType())->getElementType());
+        }
+        new StoreInst(containedTypesValue, structContainedTypesField, false, magicArrayBuildFuncInst);
+        if(!aTypeInfo->hasRawTypeRepresentation()) {
+            continue;
+        }
+
+        //handle raw array types
+        assert(aTypeInfo->getNumContainedTypes() == 1 && aTypeInfo->getContainedType(0)->getType()->isArrayTy());
+        magicArrayTypeIndexMapIt = magicArrayTypeIndexMap.find(aTypeInfo->getContainedType(0));
+        assert(magicArrayTypeIndexMapIt != magicArrayTypeIndexMap.end());
+        dstIndex = magicArrayTypeIndexMapIt->second;
+
+        //fix size field (inherited by parent type)
+        Value* srcStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+        Value* dstStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+        Value* srcStructSizeValue = new LoadInst(srcStructSizeField, "", false, magicArrayBuildFuncInst);
+        new StoreInst(srcStructSizeValue, dstStructSizeField, false, magicArrayBuildFuncInst);
+
+        //fix num_child_types field
+        Value* dstStructNumChildTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, dstIndex, 10)), MAGIC_TSTRUCT_FIELD_NUM_CHILD_TYPES);
+        Value* voidStructSizeField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, voidTypeIndex, 10)), MAGIC_TSTRUCT_FIELD_SIZE);
+        Value* voidStructSizeValue = new LoadInst(voidStructSizeField, "", false, magicArrayBuildFuncInst);
+        BinaryOperator* numChildTypesValue = BinaryOperator::Create(Instruction::SDiv, srcStructSizeValue, voidStructSizeValue, "", magicArrayBuildFuncInst);
+        new StoreInst(numChildTypesValue, dstStructNumChildTypesField, false, magicArrayBuildFuncInst);
+    }
+
+    i=0;
+    //build cast types pointers
+    for(;i<globalTypeInfos.size();i++) {
+        TypeInfo* aTypeInfo = globalTypeInfos[i];
+        std::vector<Constant*> castTypePtrs;
+        std::vector<TypeInfo*> castTypes = aTypeInfo->getCastTypes();
+
+        Value* structCompatibleTypesField = MagicUtil::getMagicTStructFieldPtr(M, magicArrayBuildFuncInst, magicTypeArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_TSTRUCT_FIELD_COMPATIBLE_TYPES);
+        TYPECONST PointerType* nullArrayType = (TYPECONST PointerType*) ((TYPECONST PointerType*)structCompatibleTypesField->getType())->getElementType();
+        for(unsigned j=0;j<castTypes.size();j++) {
+            TypeInfo* castType = castTypes[j];
+            if(castType == NULL) {
+                castTypePtrs.push_back(ConstantPointerNull::get((TYPECONST PointerType*) nullArrayType->getContainedType(0)));
+            }
+            else {
+                magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(castType);
+                assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+    
+                castTypePtrs.push_back(magicArrayTypePtrMapIt->second);
+            }
+        }
+
+        Constant *compatibleTypesValue;
+        if(castTypePtrs.size() > 0) {
+            compatibleTypesValue = MagicUtil::getArrayPtr(M, MagicUtil::getGenericArrayRef(M, castTypePtrs));
+        }
+        else {
+            compatibleTypesValue = ConstantPointerNull::get(nullArrayType);
+        }
+        new StoreInst(compatibleTypesValue, structCompatibleTypesField, false, magicArrayBuildFuncInst);
+    }
+
+    //build magic array in build function
+    i=0;
+    strGlobalVariables = 0;
+    PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+    for(;i<globalVariables.size();i++) {
+        GlobalVariable *GV = globalVariables[i];
+        DIGlobalVariable *DIGV = NULL;
+        StringRef GVName;
+        bool isFromLibrary, hasAddressTaken, isString, isNamedString;
+        isString = GV->getName().startswith(".str");
+        isNamedString = false;
+        if(isString) {
+            stringOwnerInvertedMapIt = stringOwnerInvertedMap.find(GV);
+            if(stringOwnerInvertedMapIt != stringOwnerInvertedMap.end()) {
+                isNamedString = true;
+                DIGV = NULL;
+                GVName = ".str#" + stringOwnerInvertedMapIt->second;
+            }
+        }
+        if(!isNamedString) {
+            GVName = MagicUtil::getGVSourceName(M, GV, &DIGV, baseBuildDir);
+        }
+        isFromLibrary = isExtLibrary(GV, DIGV);
+        hasAddressTaken = globalVariablesWithAddressTaken.find(GV) != globalVariablesWithAddressTaken.end();
+        std::string GVNameStr(GVName.str());
+
+        //storing id field
+        Value* structIdField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ID);
+        Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+        new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+        //storing name field
+        Value* structNameField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_NAME);
+        Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, GVNameStr));
+        new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+        //storing type field
+        parentMapIt = globalParentMap.find(GV);
+        if(parentMapIt == globalParentMap.end()) {
+            continue;
+        }
+        assert(parentMapIt != globalParentMap.end());
+        TypeInfo* aTypeInfo = parentMapIt->second;
+        magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+        assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+        Value* structTypeField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_TYPE);
+        Constant* typeValue = magicArrayTypePtrMapIt->second;
+        new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+        //filling flags field
+        int annotation, flags = MAGIC_STATE_DATA;
+        if(GV->hasExternalLinkage() || GV->hasExternalWeakLinkage()) {
+            flags |= MAGIC_STATE_EXTERNAL;
+        }
+        if(GV->isConstant()) {
+            flags |= MAGIC_STATE_CONSTANT;
+        }
+        if(GV->isThreadLocal()) {
+            flags |= MAGIC_STATE_THREAD_LOCAL;
+        }
+        if(isFromLibrary) {
+            flags |= MAGIC_STATE_LIB;
+        }
+        if(!hasAddressTaken) {
+            flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
+        }
+        if(isString) {
+            flags |= MAGIC_STATE_STRING;
+            if(isNamedString) {
+                flags |= MAGIC_STATE_NAMED_STRING;
+            }
+            strGlobalVariables++;
+        }
+        if(MagicUtil::getVarAnnotation(M, GV, &annotation)) {
+            magicPassLog("Magic annotation found for global variable: " << GV->getName());
+            flags |= (annotation & MAGIC_STATE_ANNOTATION_MASK);
+        }
+        Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
+        Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
+        new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+        //filling address field
+        Value* structAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_ADDRESS);
+        Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
+        new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
+
+        //filling shadow address field
+        Value* structShadowAddressField = MagicUtil::getMagicSStructFieldPtr(M, magicArrayBuildFuncInst, magicArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_SSTRUCT_FIELD_SHADOW_ADDRESS);
+        Constant* varShadowAddressValue;
+        if(EnableShadowing && !GV->isConstant()) {
+            GlobalVariable* varShadow = MagicUtil::getShadowRef(M, GV);
+            shadowGlobalVariables.push_back(varShadow);
+            varShadowAddressValue = ConstantExpr::getCast(Instruction::BitCast, varShadow, voidPointerType);
+        }
+        else {
+            varShadowAddressValue = ConstantPointerNull::get((TYPECONST PointerType*) ((TYPECONST PointerType*)structShadowAddressField->getType())->getElementType());
+        }
+        new StoreInst(varShadowAddressValue, structShadowAddressField, false, magicArrayBuildFuncInst);
+    }
+
+    //build magic function array in build function
+    i=0;
+    for(;i<functions.size();i++) {
+        Function *F = functions[i];
+        DISubprogram *DIS = NULL;
+        StringRef FName = MagicUtil::getFunctionSourceName(M, F, &DIS, baseBuildDir);
+        std::string FNameStr(FName.str());
+        bool isFromLibrary = isExtLibrary(F, DIS);
+
+        //storing id field
+        Value* structIdField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ID);
+        Constant* idValue = ConstantInt::get(M.getContext(), APInt(32, i+1, 10));
+        new StoreInst(idValue, structIdField, false, magicArrayBuildFuncInst);
+
+        //storing name field
+        Value* structNameField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_NAME);
+        Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, FNameStr));
+        new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+        //storing type field
+        parentMapIt = globalParentMap.find(F);
+        assert(parentMapIt != globalParentMap.end());
+        TypeInfo* aTypeInfo = parentMapIt->second;
+        magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+        assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+        Value* structTypeField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_TYPE);
+        Constant* typeValue = magicArrayTypePtrMapIt->second;
+        new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+        //filling flags field
+        int flags = MAGIC_STATE_TEXT|MAGIC_STATE_CONSTANT;
+        if(isFromLibrary) {
+            flags |= MAGIC_STATE_LIB;
+        }
+        if(!F->hasAddressTaken()) {
+            flags |= MAGIC_STATE_ADDR_NOT_TAKEN;
+        }
+        Value* structFlagsField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_FLAGS);
+        Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, flags, 10));
+        new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+
+        //filling address field
+        Value* structAddressField = MagicUtil::getMagicFStructFieldPtr(M, magicArrayBuildFuncInst, magicFunctionArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_FSTRUCT_FIELD_ADDRESS);
+        Constant* varAddressValue = ConstantExpr::getCast(Instruction::BitCast, F, voidPointerType);
+        new StoreInst(varAddressValue, structAddressField, false, magicArrayBuildFuncInst);
+    }
+
+#if MAGIC_INSTRUMENT_MEM_FUNCS
+    //replace magic memory function calls with their wrappers
+    for(i=0;i<magicMemFunctionCalls.size();i++) {
+        MagicMemFunction *magicMemFunctionCall = &magicMemFunctionCalls[i];
+        magicMemFunctionCall->replaceInstruction(magicArrayTypePtrMap, magicVoidPtrTypeInfo);
+    }
+
+    //fix debug function calls and their arguments
+    for (i=0;i<magicDebugFunctions.size();i++) {
+               MagicDebugFunction *magicDebugFunction = &magicDebugFunctions[i];
+               magicDebugFunction->fixCalls(M, baseBuildDir);
+       }
+
+    //fix mmap ctl function calls and their arguments
+    for (i=0;i<magicMmapCtlFunctions.size();i++) {
+        MagicMmapCtlFunction *magicMmapCtlFunction = &magicMmapCtlFunctions[i];
+        magicMmapCtlFunction->fixCalls(M, magicGetPageSizeFunc);
+    }
+#endif
+
+#if MAGIC_INSTRUMENT_STACK
+    //instrument the stack for the relevant set of functions and add dsindex entries
+    for(i=0;i<stackIntrumentedFuncs.size();i++) {
+        addMagicStackDsentryFuncCalls(M, stackIntrumentedFuncs[i], stackIntrumentedFuncs[i], magicStackDsentryCreateFunc, magicStackDsentryDestroyFunc,
+            magicDsentryStructType, localTypeInfoMaps[i], magicArrayTypePtrMap, magicVoidPtrTypeInfo, magicDsindexTypeInfoList, magicDsindexNamesList, magicDsindexFlagsList);
+    }
+#endif
+
+    //allocate magic dsindex array
+    ArrayType* magicDsindexArrayType = ArrayType::get(magicDsindexStructType, magicDsindexTypeInfoList.size());
+    magicDsindexArray = new GlobalVariable(M, magicDsindexArrayType, false, GlobalValue::InternalLinkage, ConstantAggregateZero::get(magicDsindexArrayType), MAGIC_DSINDEX_ARRAY_NAME);
+    MagicUtil::setGlobalVariableSection(magicDsindexArray, MAGIC_STATIC_VARS_SECTION_DATA);
+
+    //build magic dsindex array in build function
+    i=0;
+    for(;i<magicDsindexTypeInfoList.size();i++) {
+        //storing type field
+        TypeInfo* aTypeInfo = magicDsindexTypeInfoList[i];
+        magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+        assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+        Value* structTypeField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_TYPE);
+        Constant* typeValue = magicArrayTypePtrMapIt->second;
+        new StoreInst(typeValue, structTypeField, false, magicArrayBuildFuncInst);
+
+        //storing name field
+        Value* structNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_NAME);
+        Constant* nameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].second));
+        new StoreInst(nameValue, structNameField, false, magicArrayBuildFuncInst);
+
+        //storing parent name field
+        Value* structParentNameField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_PARENT_NAME);
+        Constant* parentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, magicDsindexNamesList[i].first));
+        new StoreInst(parentNameValue, structParentNameField, false, magicArrayBuildFuncInst);
+
+        //storing flags field
+        Value* structFlagsField = MagicUtil::getMagicDStructFieldPtr(M, magicArrayBuildFuncInst, magicDsindexArray, ConstantInt::get(M.getContext(), APInt(64, i, 10)), MAGIC_DSTRUCT_FIELD_FLAGS);
+        Constant* flagsValue = ConstantInt::get(M.getContext(), APInt(32, magicDsindexFlagsList[i], 10));
+        new StoreInst(flagsValue, structFlagsField, false, magicArrayBuildFuncInst);
+    }
+
+    // apply qprof instrumentation
+    qprofInstrumentationApply(M);
+
+    //set pointer to magic type array in build function
+    new StoreInst(MagicUtil::getArrayPtr(M, magicTypeArray), magicTypeArrayPtr, false, magicArrayBuildFuncInst);
+
+    //set magic type array size in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size())), magicTypeArraySize, false, magicArrayBuildFuncInst);
+
+    //set magic type next id in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalTypeInfos.size()+1)), magicTypeNextId, false, magicArrayBuildFuncInst);
+
+    //set pointer to magic array in build function
+    new StoreInst(MagicUtil::getArrayPtr(M, magicArray), magicArrayPtr, false, magicArrayBuildFuncInst);
+
+    //set magic array size in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size())), magicArraySize, false, magicArrayBuildFuncInst);
+
+    //set magic array string size in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, strGlobalVariables)), magicArrayStrSize, false, magicArrayBuildFuncInst);
+
+    //set magic next id in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, globalVariables.size()+1)), magicNextId, false, magicArrayBuildFuncInst);
+
+    //set pointer to magic function array in build function
+    new StoreInst(MagicUtil::getArrayPtr(M, magicFunctionArray), magicFunctionArrayPtr, false, magicArrayBuildFuncInst);
+
+    //set magic function array size in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size())), magicFunctionArraySize, false, magicArrayBuildFuncInst);
+
+    //set magic function next id in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, functions.size()+1)), magicFunctionNextId, false, magicArrayBuildFuncInst);
+
+    //set pointer to magic dsindex array in build function
+    new StoreInst(MagicUtil::getArrayPtr(M, magicDsindexArray), magicDsindexArrayPtr, false, magicArrayBuildFuncInst);
+
+    //set magic dsindex array size in build function
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, magicDsindexTypeInfoList.size())), magicDsindexArraySize, false, magicArrayBuildFuncInst);
+
+    //set magic void type pointer in build function
+    magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(magicVoidPtrTypeInfo);
+    assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+    Constant* magicVoidPtrTypeValue = magicArrayTypePtrMapIt->second;
+    new StoreInst(magicVoidPtrTypeValue, magicVoidPtrTypePtr, false, magicArrayBuildFuncInst);
+
+    //inject magic init call at the beginning of magic entry point function
+    std::vector<Value*> args;
+    MagicUtil::createCallInstruction(magicInitFunc, args, "", magicEntryPointFunc->getBasicBlockList().begin()->begin());
+
+    //check invariants
+#if MAGIC_CHECK_INVARIANTS
+    if(maxRecursiveSequenceLength > MAGIC_MAX_RECURSIVE_TYPES) {
+        magicPassErr("Max recursive sequence length is: " << maxRecursiveSequenceLength);
+    }
+    assert(maxRecursiveSequenceLength <= MAGIC_MAX_RECURSIVE_TYPES && "MAGIC_MAX_RECURSIVE_TYPES is too small!");
+    if(TypeInfo::getMaxNameLength() > MAGIC_MAX_NAME_LEN) {
+        magicPassErr("Max name length is: " << TypeInfo::getMaxNameLength());
+    }
+    assert(TypeInfo::getMaxNameLength() <= MAGIC_MAX_NAME_LEN && "MAGIC_MAX_NAME_LEN is too small!");
+    if(TypeInfo::getMaxTypeStringLength() > MAGIC_MAX_TYPE_STR_LEN) {
+        magicPassErr("Max type string length is: " << TypeInfo::getMaxTypeStringLength());
+    }
+    assert(TypeInfo::getMaxTypeStringLength() <= MAGIC_MAX_TYPE_STR_LEN && "MAGIC_MAX_TYPE_STR_LEN is too small!");
+#endif
+
+    return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Private methods
+//===----------------------------------------------------------------------===//
+
+static std::vector<int> currPtrVarIndexes;
+static std::set< std::pair<Value*,std::vector<int> > > visitedValues;
+
+bool MagicPass::checkPointerVariableIndexes(TYPECONST Type *type, std::vector<int> &ptrVarIndexes, unsigned offset)
+{
+    if(offset >= ptrVarIndexes.size()) {
+        return true;
+    }
+    unsigned ptrVarIndex = (unsigned) ptrVarIndexes[ptrVarIndexes.size()-1 - offset];
+    if(ptrVarIndex >= type->getNumContainedTypes()) {
+        return false;
+    }
+    return checkPointerVariableIndexes(type->getContainedType(ptrVarIndex), ptrVarIndexes, offset+1);
+}
+
+void MagicPass::findPointerVariables(Function* function, Value *value, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, Value *parent, bool isUser)
+{
+
+#define RETURN_IF(X) do{ if(X){ return; } } while(0)
+#define DEBUG_VALUE(M, V) do{ if(DEBUG_ALLOC_LEVEL >= 2) { errs() << M; V->print(errs()); errs() << "\n"; } } while(0)
+#define DEBUG_INDEXES() do{ if(DEBUG_ALLOC_LEVEL >= 3) { errs() << ">>> Indexes: "; for(unsigned i=0;i<currPtrVarIndexes.size();i++) errs() << currPtrVarIndexes[i] << " "; errs() << "\n"; } } while(0)
+
+    std::pair<Value*,std::vector<int> > visitedPair(value, currPtrVarIndexes);
+    if(visitedValues.find(visitedPair) != visitedValues.end()) {
+        return;
+    }
+
+    DEBUG_VALUE(" >>>> findPointerVariables: Value is: ", value);
+    DEBUG_VALUE(" >>>> findPointerVariables: Parent value is: ", parent);
+    DEBUG_INDEXES();
+    std::vector<int> savedPtrVarIndexes;
+    visitedValues.insert(visitedPair);
+    ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(value);
+    if(currPtrVarIndexes.size() == 0) {
+        if(DEBUG_ALLOC_LEVEL >= 2) {
+            magicPassErr("Empty indexes, skipping search path!");
+        }
+        RETURN_IF(true);
+    }
+    else if(GlobalVariable *GV = dyn_cast<GlobalVariable>(value)) {
+        if(DEBUG_ALLOC_LEVEL >= 2) {
+            magicPassErr("Found global variable!");
+        }
+        ptrVars.push_back(GV);
+        ptrVarIndexes.push_back(currPtrVarIndexes);
+        assert(!isUser);
+        if(GV->getType()->getElementType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
+            RETURN_IF(true);
+        }
+    }
+    else if(AllocaInst *AI = dyn_cast<AllocaInst>(value)) {
+        if(DEBUG_ALLOC_LEVEL >= 2) {
+            magicPassErr("Found local variable!");
+        }
+        ptrVars.push_back(AI);
+        ptrVarIndexes.push_back(currPtrVarIndexes);
+        assert(!isUser);
+        if(AI->getAllocatedType() != PointerType::get(IntegerType::get(function->getParent()->getContext(), 8), 0)) {
+            RETURN_IF(true);
+        }
+    }
+    else if(dyn_cast<ReturnInst>(value)) {
+        if(DEBUG_ALLOC_LEVEL >= 2) {
+            magicPassErr("Found return variable!");
+        }
+        assert(isUser);
+        RETURN_IF(true);
+    }
+    else if(StoreInst *SI = dyn_cast<StoreInst>(value)) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging store instruction: ", value);
+        assert(isUser);
+        if(parent == SI->getOperand(1)) {
+            assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+            currPtrVarIndexes.pop_back();
+            findPointerVariables(function, SI->getOperand(0), ptrVars, ptrVarIndexes, value);
+            currPtrVarIndexes.push_back(0);
+        }
+        else {
+            currPtrVarIndexes.push_back(0);
+            findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
+            currPtrVarIndexes.pop_back();
+        }
+    }
+    else if(LoadInst *LI = dyn_cast<LoadInst>(value)) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging load instruction: ", value);
+        if(isUser) {
+            assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+            savedPtrVarIndexes.push_back(currPtrVarIndexes.back());
+            currPtrVarIndexes.pop_back();
+        }
+        else {
+            currPtrVarIndexes.push_back(0);
+            findPointerVariables(function, LI->getOperand(0), ptrVars, ptrVarIndexes, value);
+            currPtrVarIndexes.pop_back();
+        }
+    }
+    else if(GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(value)) {
+        if(GEPI->getNumIndices() == 1) {
+            DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
+            findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
+        }
+        else {
+            RETURN_IF(isUser);
+            DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP instruction: ", value);
+            unsigned k = 0;
+            int index;
+            assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+            currPtrVarIndexes.pop_back(); //pop 0
+            for(GetElementPtrInst::const_op_iterator i=GEPI->idx_end()-1, b=GEPI->idx_begin();i>b;i--,k++) {
+                index = 0;
+                if(ConstantInt *CI = dyn_cast<ConstantInt>(*i)) {
+                    index = CI->getSExtValue();
+                }
+                currPtrVarIndexes.push_back(index);
+            }
+            currPtrVarIndexes.push_back(0); //push 0
+            findPointerVariables(function, GEPI->getOperand(0), ptrVars, ptrVarIndexes, value);
+            currPtrVarIndexes.pop_back();   //pop 0
+            while(k-->0) {
+                currPtrVarIndexes.pop_back();
+            }
+            currPtrVarIndexes.push_back(0); //push 0
+        }
+    }
+    else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+        assert(constantExpr->getNumOperands() >= 2);
+        if(constantExpr->getNumOperands() == 2) {
+            DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
+            findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
+        }
+        else {
+            RETURN_IF(isUser);
+            DEBUG_VALUE(" >>>> findPointerVariables: Digging GEP expression: ", value);
+            unsigned k = 0;
+            int index;
+            assert(currPtrVarIndexes.size() > 0 && currPtrVarIndexes[currPtrVarIndexes.size()-1] == 0);
+            currPtrVarIndexes.pop_back(); //pop 0
+            for(unsigned i=constantExpr->getNumOperands()-1;i>1;i--,k++) {
+                index = 0;
+                if(ConstantInt *CI = dyn_cast<ConstantInt>(constantExpr->getOperand(i))) {
+                    index = CI->getSExtValue();
+                }
+                currPtrVarIndexes.push_back(index);
+            }
+            currPtrVarIndexes.push_back(0); //push 0
+            findPointerVariables(function, constantExpr->getOperand(0), ptrVars, ptrVarIndexes, value);
+            currPtrVarIndexes.pop_back();   //pop 0
+            while(k-->0) {
+                currPtrVarIndexes.pop_back();
+            }
+            currPtrVarIndexes.push_back(0); //push 0
+        }
+    }
+    else if(BitCastInst *CI = dyn_cast<BitCastInst>(value)) {
+        if((isUser && !checkPointerVariableIndexes(CI->getType(), currPtrVarIndexes))
+            || (!isUser && !checkPointerVariableIndexes(CI->getOperand(0)->getType(), currPtrVarIndexes))) {
+            DEBUG_VALUE(" >>>> findPointerVariables: Skipping unsafe cast instruction: ", value);
+            RETURN_IF(true);
+        }
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging cast instruction: ", value);
+        findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
+    }
+    else if(dyn_cast<CallInst>(value) || dyn_cast<InvokeInst>(value)) {
+        RETURN_IF(isUser);
+        DEBUG_VALUE(" >>>> findPointerVariables: found call instruction: ", value);
+    }
+    else if(CmpInst *CI = dyn_cast<CmpInst>(value)) {
+        assert(isUser);
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging cmp instruction: ", value);
+        findPointerVariables(function, CI->getOperand(0), ptrVars, ptrVarIndexes, value);
+        findPointerVariables(function, CI->getOperand(1), ptrVars, ptrVarIndexes, value);
+        RETURN_IF(true);
+    }
+    else if(SelectInst *SI = dyn_cast<SelectInst>(value)) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging select instruction: ", value);
+        findPointerVariables(function, SI->getOperand(1), ptrVars, ptrVarIndexes, value);
+        findPointerVariables(function, SI->getOperand(2), ptrVars, ptrVarIndexes, value);
+    }
+    else if(constantExpr && constantExpr->getOpcode() == Instruction::Select) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging select expression: ", value);
+        findPointerVariables(function, constantExpr->getOperand(1), ptrVars, ptrVarIndexes, value);
+        findPointerVariables(function, constantExpr->getOperand(2), ptrVars, ptrVarIndexes, value);
+    }
+    else if(PHINode *PN = dyn_cast<PHINode>(value)) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging PHI instruction: ", value);
+        for(unsigned i=0;i<PN->getNumIncomingValues();i++) {
+            findPointerVariables(function, PN->getIncomingValue(i), ptrVars, ptrVarIndexes, value);
+        }
+    }
+    else if(Argument *ARG = dyn_cast<Argument>(value)) {
+        DEBUG_VALUE(" >>>> findPointerVariables: Digging Argument: ", value);
+        AllocaInst *AI = MagicUtil::getAllocaInstFromArgument(ARG);
+        assert(AI);
+        currPtrVarIndexes.push_back(0);
+        findPointerVariables(function, AI, ptrVars, ptrVarIndexes, value);
+        currPtrVarIndexes.pop_back();
+        RETURN_IF(true);
+    }
+    else {
+        DEBUG_VALUE(" ************************************************************ findPointerVariables: Unknown value: ", value);
+        RETURN_IF(true);
+    }
+    for (Value::use_iterator i = value->use_begin(), e = value->use_end(); i != e; ++i) {
+        User *user = *i;
+        Instruction *instruction = dyn_cast<Instruction>(user);
+        if(!instruction || instruction->getParent()->getParent() != function) {
+            continue;
+        }
+        DEBUG_VALUE(" >>>> findPointerVariables: Found user: ", user);
+        findPointerVariables(function, user, ptrVars, ptrVarIndexes, value, true);
+    }
+    while(savedPtrVarIndexes.size() > 0) {
+        currPtrVarIndexes.push_back(savedPtrVarIndexes.back());
+        savedPtrVarIndexes.pop_back();
+    }
+}
+
+TypeInfo* MagicPass::typeInfoFromPointerVariables(Module &M, TypeInfo *voidPtrTypeInfo, std::vector<Value*> &ptrVars, std::vector<std::vector<int> > &ptrVarIndexes, std::string &allocName)
+{
+    std::vector<TypeInfo*> validTypeInfos;
+    std::set<TypeInfo*> validTypeInfoSet;
+    std::vector<unsigned> validTypeTags;
+    std::vector<unsigned> voidTypeTags;
+    std::vector<int> indexes;
+    TypeInfo *aTypeInfo = NULL;
+    TypeInfo *voidTypeInfo = voidPtrTypeInfo->getContainedType(0);
+    allocName = "";
+    if(ptrVars.size()==0) {
+        return voidTypeInfo;
+    }
+
+    for(unsigned i=0;i<ptrVars.size();i++) {
+        DIVariable DIV;
+        unsigned tag = 0;
+        std::string varName = "";
+        if(GlobalVariable *GV = dyn_cast<GlobalVariable>(ptrVars[i])) {
+            parentMapIt = globalParentMap.find(GV);
+            assert(parentMapIt != globalParentMap.end());
+            aTypeInfo = parentMapIt->second;
+            tag = dwarf::DW_TAG_variable;
+            varName = MagicUtil::getGVSourceName(M, GV, NULL, baseBuildDir);
+        }
+        else {
+            AllocaInst *AI = dyn_cast<AllocaInst>(ptrVars[i]);
+            assert(AI);
+            if(DEBUG_ALLOC_LEVEL >= 4) {
+               AI->print(errs()); errs() << "\n";
+            }
+            const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
+            if(aSmartType == (const SmartType *)-1) {
+                //a temporary variable
+                if(DEBUG_ALLOC_LEVEL >= 4) {
+                    magicPassErr("typeInfoFromPointerVariables: Skipping temporary variable");
+                }
+                continue;
+            }
+            else if(!aSmartType) {
+                //a return variable
+                if(DEBUG_ALLOC_LEVEL >= 4) {
+                    magicPassErr("typeInfoFromPointerVariables: Processing return variable");
+                }
+                if(AI->getAllocatedType() == voidPtrTypeInfo->getType()) {
+                    aTypeInfo = voidPtrTypeInfo;
+                }
+                else {
+                    aTypeInfo = fillExternalTypeInfos(AI->getAllocatedType(), NULL, globalTypeInfos);
+                    if(aTypeInfo == NULL) {
+                        magicPassErr("typeInfoFromPointerVariables: type is: " << TypeUtil::getDescription(AI->getAllocatedType(), MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL));
+                        if(!MAGIC_ABORT_ON_UNSUPPORTED_LOCAL_EXTERNAL_TYPE) {
+                            magicPassErr("typeInfoFromPointerVariables: Warning: Local external type not supported, resorting to void* type...");
+                            aTypeInfo = voidPtrTypeInfo;
+                        }
+                        else {
+                            assert(aTypeInfo != NULL && "Local external type not supported!");
+                        }
+                    }
+                }
+                tag = dwarf::DW_TAG_unspecified_type;
+            }
+            else {
+                //a regular variable (potentially returning a value to the caller)
+                if(DEBUG_ALLOC_LEVEL >= 4) {
+                    magicPassErr("typeInfoFromPointerVariables: Processing regular variable");
+                }
+                TypeInfo newTypeInfo(aSmartType);
+                aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
+                if(aTypeInfo->getSmartType() != aSmartType) {
+                    delete aSmartType;
+                }
+                if (PassUtil::isReturnedValue(AI->getParent()->getParent(), AI)) {
+                    // treat this variable as a return variable
+                    tag = dwarf::DW_TAG_unspecified_type;
+                }
+                else {
+                    tag = DIV.getTag();
+                }
+            }
+            varName = DIV.getName();
+        }
+        //see if the target type is an alias for void*
+        assert(aTypeInfo);
+        if(aTypeInfo->getType()->isPointerTy()) {
+            stringSetIt = voidTypeAliasesSet.find(aTypeInfo->getContainedType(0)->getName());
+            if(stringSetIt != voidTypeAliasesSet.end()) {
+                aTypeInfo = voidPtrTypeInfo;
+            }
+        }
+        //fix tag if needed
+        if(tag == dwarf::DW_TAG_unspecified_type) {
+            TYPECONST Type *type = aTypeInfo->getType();
+            if(!type->isPointerTy() || type->getContainedType(0)->isPointerTy()) {
+                //not a good return type, switch to a regular variable
+                tag = dwarf::DW_TAG_auto_variable;
+            }
+        }
+        if(tag == dwarf::DW_TAG_arg_variable) {
+            TYPECONST Type *type = aTypeInfo->getType();
+            if(!type->isPointerTy() || !type->getContainedType(0)->isPointerTy() || type->getContainedType(0)->getContainedType(0)->isPointerTy()) {
+                //not a good arg type, switch to a regular variable
+                tag = dwarf::DW_TAG_auto_variable;
+            }
+        }
+        if(DEBUG_ALLOC_LEVEL >= 3) {
+            switch(tag) {
+                case dwarf::DW_TAG_unspecified_type:
+                    magicPassErr("typeInfoFromPointerVariables: Found return variable: " << varName);
+                break;
+                case dwarf::DW_TAG_variable:
+                    magicPassErr("typeInfoFromPointerVariables: Found global variable:" << varName);
+                break;
+                case dwarf::DW_TAG_auto_variable:
+                    magicPassErr("typeInfoFromPointerVariables: Found local variable:" << varName);
+                break;
+                case dwarf::DW_TAG_arg_variable:
+                    magicPassErr("typeInfoFromPointerVariables: Found argument variable:" << varName);
+                break;
+                default:
+                    assert(0 && "Should never get here!");
+                break;
+            }
+        }
+        indexes = ptrVarIndexes[i];
+        assert(indexes.back() == 0);
+        indexes.pop_back();
+        if(DEBUG_ALLOC_LEVEL >= 4) {
+            magicPassErr("typeInfoFromPointerVariables: " << indexes.size() << " indexes to process.");
+        }
+        while(!indexes.empty()) {
+            int index = indexes.back();
+            if(aTypeInfo->hasRawTypeRepresentation()) {
+                if(DEBUG_ALLOC_LEVEL >= 4) {
+                    magicPassErr("typeInfoFromPointerVariables: Skipping index (raw type representation): " << index << ", type is: " << aTypeInfo->getVerboseDescription());
+                }
+                aTypeInfo = voidTypeInfo;
+                break;
+            }
+            if(!aTypeInfo->getType()->isStructTy()) {
+                index = 0;
+            }
+            aTypeInfo = aTypeInfo->getContainedType(index);
+            if(DEBUG_ALLOC_LEVEL >= 4) {
+                magicPassErr("typeInfoFromPointerVariables: Processing index: " << index << ", type is: " << aTypeInfo->getVerboseDescription());
+            }
+            indexes.pop_back();
+        }
+        if(aTypeInfo == voidTypeInfo) {
+            voidTypeTags.push_back(tag);
+        }
+        else {
+            validTypeInfos.push_back(aTypeInfo);
+            validTypeInfoSet.insert(aTypeInfo);
+            validTypeTags.push_back(tag);
+        }
+        if(!allocName.compare("")) {
+            allocName = varName;
+        }
+    }
+    //see if we have a valid void return type
+    bool hasValidVoidReturnType = false;
+    for(unsigned i=0;i<voidTypeTags.size();i++) {
+        if(voidTypeTags[i] == dwarf::DW_TAG_unspecified_type || voidTypeTags[i] == dwarf::DW_TAG_arg_variable) {
+            hasValidVoidReturnType = true;
+            break;
+        }
+    }
+
+    //count the number of weak local types
+    unsigned numWeakLocalTypes = 0;
+    unsigned nonWeakTypeIndex = 0;
+    unsigned index = 0;
+    for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
+        if((*it)->getType() == voidTypeInfo->getType()) {
+            numWeakLocalTypes++;
+        } else {
+            nonWeakTypeIndex = index;
+        }
+        index++;
+    }
+    bool hasOnlyWeakLocalTypes = (numWeakLocalTypes == validTypeInfoSet.size());
+    bool hasOnlyOneNonWeakLocalType = (validTypeInfoSet.size() - numWeakLocalTypes == 1);
+
+    if(DEBUG_ALLOC_LEVEL >= 3) {
+        magicPassErr("typeInfoFromPointerVariables: Status: voidTypeTagsSize=" << voidTypeTags.size() << ", hasValidVoidReturnType=" << hasValidVoidReturnType << ", hasOnlyWeakLocalTypes=" << hasOnlyWeakLocalTypes << ", hasOnlyOneNonWeakLocalType=" << hasOnlyOneNonWeakLocalType);
+    }
+
+    //return NULL (treat the function as a wrapper) if we have a valid return type and only weak local types
+    if(hasValidVoidReturnType && hasOnlyWeakLocalTypes) {
+        if(DEBUG_ALLOC_LEVEL >= 3) {
+            magicPassErr("typeInfoFromPointerVariables: Returning no type at all: treat the function as a wrapper");
+        }
+        return NULL;
+    }
+
+    //a single valid type has been found, return it
+    if(hasOnlyOneNonWeakLocalType || (hasOnlyWeakLocalTypes && validTypeInfoSet.size() > 0)) {
+        if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_unspecified_type) {
+            if(DEBUG_ALLOC_BAD_TYPES) {
+                magicPassErr("typeInfoFromPointerVariables: warning: non-void return type");
+            }
+        }
+        if(validTypeTags[nonWeakTypeIndex] == dwarf::DW_TAG_arg_variable) {
+            if(DEBUG_ALLOC_BAD_TYPES) {
+                magicPassErr("typeInfoFromPointerVariables: warning: non-void arg type");
+            }
+        }
+        if(DEBUG_ALLOC_LEVEL >= 3) {
+            magicPassErr("typeInfoFromPointerVariables: Returning single valid type");
+        }
+        return validTypeInfos[nonWeakTypeIndex];
+    }
+    //multiple valid types found, print warning and resort to void
+    else if(validTypeInfoSet.size() > 1 && DEBUG_ALLOC_BAD_TYPES) {
+        magicPassErr("typeInfoFromPointerVariables: warning: multiple valid types found:");
+        for (std::set<TypeInfo*>::iterator it=validTypeInfoSet.begin() ; it != validTypeInfoSet.end(); it++ ) {
+            magicPassErr(" - " << (*it)->getVerboseDescription());
+        }
+        if(DEBUG_ALLOC_LEVEL >= 3) {
+            magicPassErr("typeInfoFromPointerVariables: Multiple valid types found");
+        }
+    }
+
+    if(DEBUG_ALLOC_LEVEL >= 3) {
+        magicPassErr("typeInfoFromPointerVariables: Returning default void type");
+    }
+    return voidTypeInfo;
+}
+
+TypeInfo* MagicPass::getAllocTypeInfo(Module &M, TypeInfo *voidPtrTypeInfo, const CallSite &CS, std::string &allocName, std::string &allocParentName)
+{
+    Value *allocPointer = NULL;
+    Function *function = MagicUtil::getCalledFunctionFromCS(CS);
+    Function *parentFunction = CS.getInstruction()->getParent()->getParent();
+    if(DEBUG_ALLOC_LEVEL >= 1) {
+        magicPassErr("Function is: " << function->getName());
+        magicPassErr("Parent is: " << parentFunction->getName());
+    }
+    std::vector<Value*> ptrVars;
+    std::vector<std::vector<int> > ptrVarIndexes;
+    currPtrVarIndexes.clear();
+    visitedValues.clear();
+    int pointerParam = MagicMemFunction::getMemFunctionPointerParam(function, brkFunctions, voidPtrTypeInfo);
+    assert(pointerParam >= 0 && "Invalid wrapper function!");
+    if(pointerParam == 0) {
+        allocPointer = CS.getInstruction();
+        currPtrVarIndexes.push_back(0);
+    }
+    else {
+        allocPointer = CS.getArgument(pointerParam-1);
+        currPtrVarIndexes.push_back(0);
+        //brk is a special case and takes the pointer by value
+        if(brkFunctions.find(function) == brkFunctions.end()) {
+            currPtrVarIndexes.push_back(0);
+        }
+    }
+    findPointerVariables(parentFunction, allocPointer, ptrVars, ptrVarIndexes);
+    TypeInfo* aTypeInfo = typeInfoFromPointerVariables(M, voidPtrTypeInfo, ptrVars, ptrVarIndexes, allocName);
+    allocParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseBuildDir);
+    if(DEBUG_ALLOC_LEVEL >= 1) {
+        magicPassErr("**************** type found: " << (aTypeInfo ? aTypeInfo->getType()->isStructTy() ? "struct " + aTypeInfo->getName() : aTypeInfo->getVerboseDescription() : "NULL"));
+    }
+    return aTypeInfo;
+}
+
+TypeInfo* MagicPass::fillTypeInfos(TypeInfo &sourceTypeInfo, std::vector<TypeInfo*> &typeInfos) {
+    static std::vector<TypeInfo*> nestedTypes;
+    static unsigned level = 0;
+    if(DEBUG_FILL_TYPE_INFOS) {
+        magicPassErr("Entering level: " << level << ", Examining type: " << sourceTypeInfo.getDescription() << ", types so far: " << typeInfos.size());
+    }
+
+    if(sourceTypeInfo.getType()) {
+        TYPECONST Type* type = sourceTypeInfo.getType();
+        for(unsigned i=0;i<nestedTypes.size();i++) {
+            if(type == nestedTypes[i]->getType()) {
+                const SmartType *nestedSType = nestedTypes[i]->getSmartType();
+                const SmartType *sourceSType = sourceTypeInfo.getSmartType();
+                if((!nestedSType && !sourceSType) || (nestedSType && sourceSType && nestedSType->getEDIType()->equals(sourceSType->getEDIType()))) {
+                    nestedTypes[i]->addParents(sourceTypeInfo.getParents());
+                    return nestedTypes[i];
+                }
+            }
+        }
+    }
+    assert(sourceTypeInfo.getParents().size() <= 1);
+    for(unsigned i=0;i<typeInfos.size();i++) {
+        if(typeInfos[i]->equals(&sourceTypeInfo)) {
+            typeInfos[i]->addParents(sourceTypeInfo.getParents());
+            return typeInfos[i];
+        }
+    }
+    TypeInfo *aTypeInfo = new TypeInfo(sourceTypeInfo);
+    aTypeInfo->setPersistent();
+    const SmartType *aSmartType = aTypeInfo->getSmartType();
+    unsigned numContainedTypes = aSmartType ? aSmartType->getNumContainedTypes() : 0;
+    const SmartType* containedSmartType = NULL;
+    TypeInfo* addedTypeInfo = NULL;
+    std::vector<TypeInfo*> aTypeInfoContainedTypes;
+    nestedTypes.push_back(aTypeInfo);
+    level++;
+    for(unsigned i=0;i<numContainedTypes;i++) {
+        containedSmartType = aSmartType->getContainedType(i);
+        if(!containedSmartType->isFunctionTy() || containedSmartType->isTypeConsistent()) {
+            TypeInfo containedTypeInfo(containedSmartType);
+            addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
+        }
+        else {
+            TYPECONST FunctionType* type = (TYPECONST FunctionType*) containedSmartType->getType();
+            TypeInfo containedTypeInfo(type);
+            addedTypeInfo = fillTypeInfos(containedTypeInfo, typeInfos);
+        }
+        if(addedTypeInfo->getSmartType() != containedSmartType) {
+            delete containedSmartType;
+        }
+        aTypeInfoContainedTypes.push_back(addedTypeInfo);
+    }
+    level--;
+    nestedTypes.pop_back();
+    aTypeInfo->setContainedTypes(aTypeInfoContainedTypes);
+    typeInfos.push_back(aTypeInfo);
+    if(DEBUG_FILL_TYPE_INFOS) {
+        magicPassErr("Exiting level: " << level << ", types so far: " << typeInfos.size());
+    }
+    return aTypeInfo;
+}
+
+TypeInfo* MagicPass::fillExternalTypeInfos(TYPECONST Type *sourceType, GlobalValue* parent, std::vector<TypeInfo*> &typeInfos) {
+    static std::map<TYPECONST Type *, TypeInfo*> externalTypeInfoCache;
+    std::map<TYPECONST Type*, TypeInfo*>::iterator externalTypeInfoCacheIt;
+    TypeInfo* aTypeInfo = NULL;
+    std::vector<TypeInfo*> compatibleTypeInfos;
+    //see if we already have the type in the cache first
+    externalTypeInfoCacheIt = externalTypeInfoCache.find(sourceType);
+    if(externalTypeInfoCacheIt != externalTypeInfoCache.end()) {
+        aTypeInfo = externalTypeInfoCacheIt->second;
+        if(parent) {
+            aTypeInfo->addParent(parent);
+        }
+        return aTypeInfo;
+    }
+
+    for(unsigned i=0;i<typeInfos.size();i++) {
+        if(typeInfos[i]->getSmartType() && typeInfos[i]->getSmartType()->getType() == sourceType && (!sourceType->isArrayTy() || typeInfos[i]->getTypeID() == MAGIC_TYPE_ARRAY)) {
+            compatibleTypeInfos.push_back(typeInfos[i]);
+        }
+    }
+    if(compatibleTypeInfos.size() > 0) {
+        unsigned minStringTypeInfo = 0;
+        if(compatibleTypeInfos.size() > 1) {
+            /* Select the first type in alphabetical order to ensure deterministic behavior. */
+            for(unsigned i=1;i<compatibleTypeInfos.size();i++) {
+                if(compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription().compare(compatibleTypeInfos[minStringTypeInfo]->getSmartType()->getEDIType()->getDescription()) < 0) {
+                    minStringTypeInfo = i;
+                }
+            }
+        }
+        aTypeInfo = compatibleTypeInfos[minStringTypeInfo];
+    }
+    if(DEBUG_FILL_EXT_TYPE_INFOS && compatibleTypeInfos.size() > 1) {
+        std::string typeString;
+        for(unsigned i=0;i<compatibleTypeInfos.size();i++) {
+            assert(compatibleTypeInfos[i]->getSmartType());
+            typeString += (i==0 ? "" : ", ") + compatibleTypeInfos[i]->getSmartType()->getEDIType()->getDescription();
+        }
+        magicPassErr("Multiple compatible types found for external type " << TypeUtil::getDescription(sourceType, MAGIC_TYPE_STR_PRINT_MAX, MAGIC_TYPE_STR_PRINT_MAX_LEVEL) << ": " << typeString << "; selecting the first type in alphabetical order: " << aTypeInfo->getSmartType()->getEDIType()->getDescription());
+    }
+    if(aTypeInfo == NULL) {
+        TypeInfo *targetTypeInfo = NULL;
+        if(TypeUtil::isOpaqueTy(sourceType)) {
+            aTypeInfo = new TypeInfo((TYPECONST StructType*) sourceType, TYPEINFO_PERSISTENT);
+            typeInfos.push_back(aTypeInfo);
+        }
+        else if(sourceType->isPointerTy()) {
+            TYPECONST Type *targetType = sourceType->getContainedType(0);
+            targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
+            if(targetTypeInfo == NULL) {
+                return NULL;
+            }
+            aTypeInfo = new TypeInfo((TYPECONST PointerType*) sourceType, TYPEINFO_PERSISTENT);
+        }
+        else if(sourceType->isArrayTy()) {
+            TYPECONST Type *targetType = sourceType->getContainedType(0);
+            targetTypeInfo = fillExternalTypeInfos(targetType, NULL, typeInfos);
+            if(targetTypeInfo == NULL) {
+                return NULL;
+            }
+            aTypeInfo = new TypeInfo((TYPECONST ArrayType*) sourceType, TYPEINFO_PERSISTENT);
+        }
+        else if(sourceType->isIntegerTy()) {
+            aTypeInfo = new TypeInfo((TYPECONST IntegerType*) sourceType, TYPEINFO_PERSISTENT);
+            typeInfos.push_back(aTypeInfo);
+        }
+        else if(sourceType->isFunctionTy()) {
+            aTypeInfo = new TypeInfo((TYPECONST FunctionType*) sourceType, TYPEINFO_PERSISTENT);
+            typeInfos.push_back(aTypeInfo);
+        }
+        if(targetTypeInfo != NULL) {
+            std::vector<TypeInfo*> containedTypes;
+            containedTypes.push_back(targetTypeInfo);
+            aTypeInfo->setContainedTypes(containedTypes);
+            typeInfos.push_back(aTypeInfo);
+        }
+    }
+    if(aTypeInfo && parent) {
+        aTypeInfo->addParent(parent);
+    }
+    externalTypeInfoCache.insert(std::pair<TYPECONST Type*, TypeInfo*>(sourceType, aTypeInfo));
+    return aTypeInfo;
+}
+
+void MagicPass::printInterestingTypes(TYPECONST TypeInfo *aTypeInfo) {
+    static std::vector<TYPECONST TypeInfo*> nestedTypes;
+    static std::vector<unsigned> nestedIndexes;
+    static std::vector<TYPECONST TypeInfo*> interestingTypesSoFar;
+    static std::string typeName;
+    static unsigned level = 0;
+    for(unsigned i=0;i<nestedTypes.size();i++) {
+        if(aTypeInfo == nestedTypes[i]) {
+            return;
+        }
+    }
+
+    bool isInterestingType = false;
+    const SmartType *aSmartType = aTypeInfo->getSmartType();
+    if(aSmartType) {
+        if(aSmartType->isStructTy() && !aTypeInfo->getName().compare("")) {
+            isInterestingType = true;
+            typeName = "Anonymous";
+        }
+        if(aSmartType->getEDIType()->isEnumTy()) {
+            isInterestingType = true;
+            typeName = "Enum";
+        }
+        if(aSmartType->isOpaqueTy()) {
+            isInterestingType = true;
+            typeName = "Opaque";
+        }
+    }
+    if(isInterestingType) {
+        bool isNewInterestingType = true;
+        for(unsigned i=0;i<interestingTypesSoFar.size();i++) {
+            if(aTypeInfo == interestingTypesSoFar[i]) {
+                isNewInterestingType = false;
+                break;
+            }
+        }
+        if(isNewInterestingType) {
+            interestingTypesSoFar.push_back(aTypeInfo);
+            if(nestedTypes.size() == 0) {
+                dbgs() << "**** " << typeName << " top type found, printing it: \n";
+                dbgs() << aSmartType->getDescription();
+                aSmartType->getEDIType()->getDIType()->print(dbgs());
+            }
+            else {
+                dbgs() << "**** " << typeName << " type found, printing path: \n";
+                dbgs() << "**************** LEVEL 0\n";
+                dbgs() << "**************** NAME: " << nestedTypes[0]->getName() << "\n";
+                dbgs() << nestedTypes[0]->getSmartType()->getDescription();
+                unsigned i;
+                for(i=1;i<nestedTypes.size();i++) {
+                    dbgs() << "**************** LEVEL " << i << "\n";
+                    dbgs() << "**************** NAME: " << nestedTypes[i]->getName() << "\n";
+                    dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
+                    dbgs() << nestedTypes[i]->getSmartType()->getDescription();
+                }
+                dbgs() << "**************** LAST LEVEL " << i << "\n";
+                dbgs() << "**************** PARENT INDEX " << nestedIndexes[i-1] << "\n";
+                dbgs() << aSmartType->getDescription();
+                aSmartType->getEDIType()->getDIType()->print(dbgs());
+                dbgs() << "*****************************************\n";
+            }
+        }
+    }
+
+    unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
+    nestedTypes.push_back(aTypeInfo);
+    level++;
+    for(unsigned i=0;i<numContainedTypes;i++) {
+        nestedIndexes.push_back(i);
+        printInterestingTypes(aTypeInfo->getContainedType(i));
+        nestedIndexes.pop_back();
+    }
+    level--;
+    nestedTypes.pop_back();
+}
+
+unsigned MagicPass::getMaxRecursiveSequenceLength(TYPECONST TypeInfo *aTypeInfo) {
+    static std::vector<TYPECONST TypeInfo*> nestedTypes;
+    static unsigned level = 0;
+    for(unsigned i=0;i<nestedTypes.size();i++) {
+        if(aTypeInfo == nestedTypes[i]) {
+            return nestedTypes.size()+1;
+        }
+    }
+
+    unsigned numContainedTypes = aTypeInfo->getNumContainedTypes();
+    unsigned length, maxLength = 0;
+    nestedTypes.push_back(aTypeInfo);
+    level++;
+    for(unsigned i=0;i<numContainedTypes;i++) {
+        length = getMaxRecursiveSequenceLength(aTypeInfo->getContainedType(i));
+        if(length > maxLength) {
+            maxLength = length;
+        }
+    }
+    level--;
+    nestedTypes.pop_back();
+    return maxLength;
+}
+
+FunctionType* MagicPass::getFunctionType(TYPECONST FunctionType *baseType, std::vector<unsigned> selectedArgs) {
+       std::vector<TYPECONST Type*> ArgTypes;
+       for (unsigned i = 0; i < selectedArgs.size(); i++) {
+               ArgTypes.push_back(baseType->getParamType(selectedArgs[i] - 1));
+       }
+       // Create a new function type...
+       FunctionType *FTy = FunctionType::get(baseType->getReturnType(), ArgTypes, baseType->isVarArg());
+       return FTy;
+}
+
+bool MagicPass::isCompatibleMagicMemFuncType(TYPECONST FunctionType *type, TYPECONST FunctionType* magicType) {
+    if(type->getReturnType() != magicType->getReturnType()) {
+        return false;
+    }
+    unsigned numContainedTypes = type->getNumContainedTypes();
+    unsigned numContainedMagicTypes = magicType->getNumContainedTypes();
+    if(numContainedTypes > numContainedMagicTypes) {
+        return false;
+    }
+    for(unsigned i=0;i<numContainedTypes-1;i++) {
+        TYPECONST Type* cType = type->getContainedType(numContainedTypes-1-i);
+        TYPECONST Type* cMagicType = magicType->getContainedType(numContainedMagicTypes-1-i);
+        if (!MagicUtil::isCompatibleType(cType, cMagicType)) {
+               return false;
+        }
+    }
+    return true;
+}
+
+void MagicPass::indexCasts(Module &M, User *U, std::vector<TYPECONST Type*> &intCastTypes, std::vector<int> &intCastValues, std::map<TYPECONST Type*, std::set<TYPECONST Type*> > &bitCastMap) {
+    unsigned i;
+    std::map<TYPECONST Type*, std::set<TYPECONST Type*> >::iterator bitCastMapIt;
+    TYPECONST Type* voidPtrType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+
+    //look at instructions first
+#if MAGIC_INDEX_INT_CAST
+    if(CastInst* CI = dyn_cast<IntToPtrInst>(U)) {
+        TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
+        TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+        if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
+            if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
+                intCastTypes.push_back(type);
+                ConstantInt *value = dyn_cast<ConstantInt>(CI->getOperand(0));
+                intCastValues.push_back(value ? value->getSExtValue() : 0);
+#if DEBUG_CASTS
+                CI->print(errs()); errs() << "\n";
+#endif
+            }
+        }
+    }
+#endif
+
+#if MAGIC_INDEX_BIT_CAST
+    if(BitCastInst* CI = dyn_cast<BitCastInst>(U)) {
+        TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CI->getDestTy());
+        TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+        if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
+            if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
+                TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CI->getSrcTy());
+                if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
+#if DEBUG_CASTS
+                    CI->print(errs()); errs() << "\n";
+#endif
+                    bitCastMapIt = bitCastMap.find(type);
+                    if(bitCastMapIt == bitCastMap.end()) {
+                        std::set<TYPECONST Type*> typeSet;
+                        typeSet.insert(srcType);
+                        bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
+                    }
+                    else {
+                        std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
+                        typeSet->insert(srcType);
+                    }
+                }
+            }
+        }
+    }
+#endif
+
+    //now dig looking for constant expressions
+    std::vector<User*> users;
+    users.push_back(U);
+    while(!users.empty()) {
+        User *user = users.front();
+        users.erase(users.begin());
+        ConstantExpr *CE = dyn_cast<ConstantExpr>(user);
+
+#if MAGIC_INDEX_INT_CAST
+        if(CE && CE->getOpcode() == Instruction::IntToPtr) {
+            TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
+            TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+            if((MAGIC_INDEX_FUN_PTR_INT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_INT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_INT_CAST) {
+                if(MAGIC_INDEX_VOID_PTR_INT_CAST || type != voidPtrType) {
+#if DEBUG_CASTS
+                    CE->print(errs()); errs() << "\n";
+#endif
+                    intCastTypes.push_back(type);
+                    ConstantInt *value = dyn_cast<ConstantInt>(CE->getOperand(0));
+                    intCastValues.push_back(value ? value->getSExtValue() : 0);
+                }
+            }
+        }
+#endif
+
+#if MAGIC_INDEX_BIT_CAST
+        if(CE && CE->getOpcode() == Instruction::BitCast) {
+            TYPECONST Type* type = TypeUtil::getArrayFreePointerType(CE->getType());
+            TYPECONST Type* elType = TypeUtil::getRecursiveElementType(type);
+            if((MAGIC_INDEX_FUN_PTR_BIT_CAST && elType->isFunctionTy()) || (MAGIC_INDEX_STR_PTR_BIT_CAST && elType->isStructTy()) || MAGIC_INDEX_OTH_PTR_BIT_CAST) {
+                if(MAGIC_INDEX_VOID_PTR_BIT_CAST || type != voidPtrType) {
+                    TYPECONST Type* srcType = TypeUtil::getArrayFreePointerType(CE->getOperand(0)->getType());
+                    if(srcType != type && (!MAGIC_SKIP_TOVOID_PTR_BIT_CAST || srcType != voidPtrType)) {
+#if DEBUG_CASTS
+                        CE->print(errs()); errs() << "\n";
+#endif
+                        bitCastMapIt = bitCastMap.find(type);
+                        if(bitCastMapIt == bitCastMap.end()) {
+                            std::set<TYPECONST Type*> typeSet;
+                            typeSet.insert(srcType);
+                            bitCastMap.insert(std::pair<TYPECONST Type*, std::set<TYPECONST Type*> >(type, typeSet));
+                        }
+                        else {
+                            std::set<TYPECONST Type*> *typeSet = &(bitCastMapIt->second);
+                            typeSet->insert(srcType);
+                        }
+                    }
+                }
+            }
+        }
+#endif
+
+        for(i=0;i<user->getNumOperands();i++) {
+            User *operand = dyn_cast<User>(user->getOperand(i));
+            if(operand && !isa<Instruction>(operand) && !isa<GlobalVariable>(operand)) {
+                users.push_back(operand);
+            }
+        }
+    }
+}
+
+void MagicPass::fillStackInstrumentedFunctions(std::vector<Function*> &stackIntrumentedFuncs, Function *deepestLLFunction) {
+    assert(!deepestLLFunction->hasAddressTaken() && "Indirect calls not supported for detection of long-lived functions");
+    for(unsigned i=0;i<stackIntrumentedFuncs.size();i++) {
+        if(stackIntrumentedFuncs[i] == deepestLLFunction) {
+            return;
+        }
+    }
+    stackIntrumentedFuncs.push_back(deepestLLFunction);
+    for (Value::use_iterator i = deepestLLFunction->use_begin(), e = deepestLLFunction->use_end(); i != e; ++i) {
+        User *user = *i;
+        if(Instruction *I = dyn_cast<Instruction>(user)) {
+            fillStackInstrumentedFunctions(stackIntrumentedFuncs, I->getParent()->getParent());
+        }
+    }
+}
+
+void MagicPass::indexLocalTypeInfos(Module &M, Function *F, std::map<AllocaInst*, std::pair<TypeInfo*, std::string> > &localMap) {
+  DIVariable DIV;
+  for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
+      AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+      if(!AI) {
+          break;
+      }
+      const SmartType *aSmartType = SmartType::getSmartTypeFromLV(M, AI, &DIV);
+      if(!aSmartType || aSmartType == (const SmartType *)-1) {
+          // skip return and temporary variables
+          continue;
+      }
+      TypeInfo newTypeInfo(aSmartType);
+      TypeInfo *aTypeInfo = fillTypeInfos(newTypeInfo, globalTypeInfos);
+      if(aTypeInfo->getSmartType() != aSmartType) {
+          delete aSmartType;
+      }
+      std::string name = MagicUtil::getLVSourceName(M, AI).data();
+      std::pair<TypeInfo*, std::string> infoNamePair(aTypeInfo, name);
+      localMap.insert(std::pair<AllocaInst*, std::pair<TypeInfo*, std::string> >(AI, infoNamePair));
+  }
+}
+
+void MagicPass::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) {
+  std::vector<Value*> locals;
+  std::map<AllocaInst*, std::pair<TypeInfo*, std::string> >::iterator localTypeInfoMapIt;
+  std::map<TypeInfo*, Constant*>::iterator magicArrayTypePtrMapIt;
+  std::vector<TypeInfo*> localTypeInfos;
+  std::vector<Value*> localTypeInfoValues;
+  std::vector<Value*> localDsentryValues;
+  std::string allocName, allocParentName;
+  Instruction *allocaI = NULL, *dsentryCreateI = NULL, *dsentryDestroyI = NULL;
+  // find local variables and types
+  for (inst_iterator it = inst_begin(localsFromFunc), et = inst_end(localsFromFunc); it != et; ++it) {
+      AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+      if(!AI) {
+          break;
+      }
+      localTypeInfoMapIt = localTypeInfoMap.find(AI);
+      if(localTypeInfoMapIt != localTypeInfoMap.end()) {
+          assert(AI->hasName());
+          TypeInfo *aTypeInfo = localTypeInfoMapIt->second.first;
+          magicArrayTypePtrMapIt = magicArrayTypePtrMap.find(aTypeInfo);
+          assert(magicArrayTypePtrMapIt != magicArrayTypePtrMap.end());
+          Constant *aTypeInfoValue = magicArrayTypePtrMapIt->second;
+          localTypeInfos.push_back(aTypeInfo);
+          localTypeInfoValues.push_back(aTypeInfoValue);
+          locals.push_back(AI);
+      }
+  }
+  // find the first and the last valid instruction to place a call and the alloca point
+  dsentryCreateI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc);
+  dsentryDestroyI = insertCallsInFunc->back().getTerminator();
+  allocaI = MagicUtil::getFirstNonAllocaInst(insertCallsInFunc, false);
+
+  // create one dsentry for each local variable
+  for(unsigned i=0;i<locals.size();i++) {
+      AllocaInst *AI = new AllocaInst(dsentryStructType, "dsentry_" + (locals[i]->hasName() ? locals[i]->getName() : "anon"), allocaI);
+      localDsentryValues.push_back(AI);
+  }
+  assert(localTypeInfoValues.size() == localDsentryValues.size());
+
+  // create one dsentry and value set array for the return address
+  localTypeInfos.push_back(voidPtrTypeInfo);
+  localTypeInfoValues.push_back(new AllocaInst(ArrayType::get(IntegerType::get(M.getContext(), 32), 2), "dsentry_ret_addr_value_set", allocaI)); //pass the value set pointer as though it were a type pointer
+  localDsentryValues.push_back(new AllocaInst(dsentryStructType, "dsentry_ret_addr", allocaI));
+
+  // create one dsentry pointer to remember the last stack dsentry
+  AllocaInst *prevLastStackDsentry = new AllocaInst(PointerType::get(dsentryStructType, 0), "prev_last_stack_dsentry", allocaI);
+
+  // get the frame address of the function and pass the value as though it were a data pointer
+  Function *frameAddrIntrinsic = MagicUtil::getIntrinsicFunction(M, Intrinsic::frameaddress);
+  std::vector<Value*> frameAddrArgs;
+  frameAddrArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, 0)));
+  CallInst *callInst = MagicUtil::createCallInstruction(frameAddrIntrinsic, frameAddrArgs, "", dsentryCreateI);
+  locals.push_back(callInst);
+
+  // place calls
+  std::vector<Value*> dsentryCreateArgs;
+  std::vector<Value*> dsentryDestroyArgs;
+  dsentryCreateArgs.push_back(prevLastStackDsentry);
+  dsentryDestroyArgs.push_back(prevLastStackDsentry);
+  dsentryCreateArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
+  dsentryDestroyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, locals.size())));
+  allocParentName = MagicUtil::getFunctionSourceName(M, insertCallsInFunc, NULL, baseBuildDir);
+  int allocFlags = MAGIC_STATE_STACK;
+  for(unsigned i=0;i<locals.size();i++) {
+      //get name
+      if(AllocaInst *AI = dyn_cast<AllocaInst>(locals[i])) {
+          // local variable
+          localTypeInfoMapIt = localTypeInfoMap.find(AI);
+          assert(localTypeInfoMapIt != localTypeInfoMap.end());
+          allocName = localTypeInfoMapIt->second.second;
+      }
+      else {
+          // return address
+          allocName = MAGIC_ALLOC_RET_ADDR_NAME;
+      }
+      //add args
+      dsentryCreateArgs.push_back(localDsentryValues[i]);
+      dsentryCreateArgs.push_back(localTypeInfoValues[i]);
+      dsentryCreateArgs.push_back(locals[i]);
+      dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocParentName));
+      dsentryCreateArgs.push_back(MagicUtil::getStringRef(M, allocName));
+      dsentryDestroyArgs.push_back(localDsentryValues[i]);
+      //add elements to type and names lists
+      typeInfoList.push_back(localTypeInfos[i]);
+      namesList.push_back(std::pair<std::string, std::string>(allocParentName, allocName));
+      flagsList.push_back(allocFlags);
+  }
+  MagicUtil::createCallInstruction(dsentryCreateFunc, dsentryCreateArgs, "", dsentryCreateI);
+  if(isa<ReturnInst>(dsentryDestroyI)) {
+      MagicUtil::createCallInstruction(dsentryDestroyFunc, dsentryDestroyArgs, "", dsentryDestroyI);
+  }
+}
+
+bool MagicPass::isExtLibrary(GlobalValue *GV, DIDescriptor *DID)
+{
+    static bool regexesInitialized = false;
+    static std::vector<Regex*> regexes;
+    if(!regexesInitialized) {
+        std::vector<std::string>::iterator it;
+        for (it = libPathRegexes.begin(); it != libPathRegexes.end(); ++it) {
+            Regex* regex = new Regex(*it, 0);
+            std::string error;
+            assert(regex->isValid(error));
+            regexes.push_back(regex);
+        }
+        regexesInitialized = true;
+    }
+    if (DID) {
+       std::string relPath;
+       PassUtil::getDbgLocationInfo(*DID, baseBuildDir, NULL, NULL, &relPath);
+        for(unsigned i=0;i<regexes.size();i++) {
+            if(regexes[i]->match(relPath, NULL)) {
+                return true;
+            }
+        }
+    }
+    return PassUtil::matchRegexes(GV->getSection(), extLibSectionRegexes);
+}
+
+bool MagicPass::isMagicGV(Module &M, GlobalVariable *GV)
+{
+    if (GV->isThreadLocal() && (GV->getName().startswith(MAGIC_PREFIX_STR) || GV->getName().startswith("rcu"))) {
+        return true;
+    }
+    if (!GV->getSection().compare(MAGIC_LLVM_METADATA_SECTION)) {
+       return true;
+    }
+    if (GV->getName().startswith("__start") || GV->getName().startswith("__stop") || GV->getName().startswith("llvm.")) {
+        return true;
+    }
+    return PassUtil::matchRegexes(GV->getSection(), magicDataSectionRegexes);
+}
+
+bool MagicPass::isMagicFunction(Module &M, Function *F)
+{
+       if (F->getName().startswith("llvm.")) return true;
+    return PassUtil::matchRegexes(F->getSection(), magicFunctionSectionRegexes);
+}
+
+#if MAGIC_USE_QPROF_INSTRUMENTATION
+
+void MagicPass::qprofInstrumentationInit(Module &M)
+{
+    // look up qprof configuration
+    qprofConf = QProfConf::get(M, &magicLLSitestacks,
+        &magicDeepestLLLoops,
+        &magicDeepestLLLibs,
+        &magicTaskClasses);
+    qprofConf->mergeAllTaskClassesWithSameDeepestLLLoops();
+
+#if DEBUG_QPROF
+    qprofConf->print(errs());
+#endif
+}
+
+void MagicPass::qprofInstrumentationApply(Module &M)
+{
+    Function *hook;
+    std::vector<Value*> hookParams;
+    QProfSite* site;
+    std::vector<TYPECONST Type*>functionTyArgs;
+    FunctionType *hookFunctionTy;
+
+    /*
+     * Instrument deepest long-lived loops. This creates a function
+     * pointer of the form void (*MAGIC_DEEPEST_LL_LOOP_HOOK_NAME)(char*, int)
+     * called (if set by instrumentation libraries) at the top of every loop.
+     */
+    functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
+    functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+    hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
+    std::vector<QProfSite*> deepestLLLoops = qprofConf->getDeepestLLLoops();
+    hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LOOP_HOOK_NAME, hookFunctionTy,
+        PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+    assert(hook);
+    for (unsigned i=0;i<deepestLLLoops.size();i++) {
+        site = deepestLLLoops[i];
+        hookParams.clear();
+        Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
+        hookParams.push_back(siteString);
+        hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
+        PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
+    }
+
+    /*
+     * Instrument deepest long-lived library calls. This creates a function
+     * pointer of the form void (*MAGIC_DEEPEST_LL_LIB_HOOK_NAME)(char*, int, int, int)
+     * called (if set by instrumentation libraries) before every library call.
+     */
+    functionTyArgs.clear();
+    functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0));
+    functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+    functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+    functionTyArgs.push_back(IntegerType::get(M.getContext(), 32));
+    hookFunctionTy = PassUtil::getFunctionType(Type::getVoidTy(M.getContext()), functionTyArgs, false);
+    std::vector<QProfSite*> deepestLLLibs = qprofConf->getDeepestLLLibs();
+    hook = PassUtil::getOrInsertFunction(M, MAGIC_DEEPEST_LL_LIB_HOOK_NAME, hookFunctionTy,
+        PASS_UTIL_LINKAGE_WEAK_POINTER, PASS_UTIL_FLAG(PASS_UTIL_PROP_PRESERVE));
+    assert(hook);
+    for (unsigned i=0;i<deepestLLLibs.size();i++) {
+        site = deepestLLLibs[i];
+        hookParams.clear();
+        Constant* siteString = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, site->toString()));
+        hookParams.push_back(siteString);
+        hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskClassID, 10)));
+        hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->taskSiteID, 10)));
+        hookParams.push_back(ConstantInt::get(M.getContext(), APInt(32, site->libFlags, 10)));
+        PassUtil::createCallInstruction(hook, hookParams, "", site->siteInstruction);
+    }
+
+    /*
+     * Create relevant exported variables in use by the libraries.
+     */
+    MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_TASK_CLASSES_NAME, qprofConf->getNumLLTaskClasses());
+    MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockExtTaskClasses());
+    MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_TASK_CLASSES_NAME, qprofConf->getNumLLBlockIntTaskClasses());
+    MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_EXT_LIBS_NAME, qprofConf->getNumLLBlockExtLibs());
+    MagicUtil::getExportedIntGlobalVar(M, MAGIC_NUM_LL_BLOCK_INT_LIBS_NAME, qprofConf->getNumLLBlockIntLibs());
+}
+
+#else
+
+void MagicPass::qprofInstrumentationInit(Module &M) {}
+void MagicPass::qprofInstrumentationApply(Module &M) {}
+
+#endif
+
+} // end namespace 
+
+char MagicPass::ID = 0;
+RegisterPass<MagicPass> MP("magic", "Magic Pass to Build a Table of Global Variables");
+
diff --git a/minix/llvm/passes/magic/Makefile b/minix/llvm/passes/magic/Makefile
new file mode 100644 (file)
index 0000000..9d89f58
--- /dev/null
@@ -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
diff --git a/minix/llvm/passes/magic/support/Backports.cpp b/minix/llvm/passes/magic/support/Backports.cpp
new file mode 100644 (file)
index 0000000..748ae50
--- /dev/null
@@ -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
+}
+
+}
diff --git a/minix/llvm/passes/magic/support/BitFieldAggregation.cpp b/minix/llvm/passes/magic/support/BitFieldAggregation.cpp
new file mode 100644 (file)
index 0000000..c107d93
--- /dev/null
@@ -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;
+
+}
diff --git a/minix/llvm/passes/magic/support/EDIType.cpp b/minix/llvm/passes/magic/support/EDIType.cpp
new file mode 100644 (file)
index 0000000..bea74a1
--- /dev/null
@@ -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;
+
+}
diff --git a/minix/llvm/passes/magic/support/MagicUtil.cpp b/minix/llvm/passes/magic/support/MagicUtil.cpp
new file mode 100644 (file)
index 0000000..7c38871
--- /dev/null
@@ -0,0 +1,1137 @@
+#include <magic/support/MagicUtil.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Public static methods
+//===----------------------------------------------------------------------===//
+
+static std::map<const std::string, GlobalVariable*> stringRefCache;
+
+unsigned getLabelHash(std::string label) {
+    unsigned hash = 0;
+    for(unsigned i=0;i<label.length();i++){
+        hash ^= (label[i]);
+        hash = (hash << 9) | (hash >> ((sizeof(unsigned)*8)-9));
+    }
+    return hash;
+}
+
+unsigned getModuleHash(DIDescriptor DID, const std::string &baseDir, StringRef extraField="") {
+    std::string relPath;
+    PassUtil::getDbgLocationInfo(DID, baseDir, NULL, NULL, &relPath);
+    return getLabelHash(relPath + "/" + extraField.data());
+}
+
+StringRef MagicUtil::getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP, const std::string &baseDir) {
+    static DIGlobalVariable Var;
+    Value *DIGV = Backports::findDbgGlobalDeclare(GV);
+    if(DIGV) {
+        Var = DIGlobalVariable(cast<MDNode>(DIGV));
+        if(DIGVP) *DIGVP = &Var;
+        if(GV->getLinkage() == GlobalValue::InternalLinkage){
+            /* static variable */
+            StringRef funcName, countStr;
+            DIScope scope = Var.getContext();
+            if(scope.isLexicalBlock()){
+                /* find the subprogram that contains this basic block recursively */
+                while(!scope.isSubprogram()){
+                    scope = DILexicalBlock(scope).getContext();
+                }
+            }
+            if(scope.isSubprogram()){
+                /* static function variable */
+
+                funcName = DISubprogram(scope).getName();
+
+                int count=0; 
+                Module::GlobalListType &globalList = M.getGlobalList();
+                for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
+                    GlobalVariable *OtherGV = &(*it);
+                    Value *OtherDIGV = Backports::findDbgGlobalDeclare(OtherGV);
+                    if(OtherDIGV) {
+                        DIGlobalVariable OtherVar(cast<MDNode>(OtherDIGV));
+
+                        DIScope otherScope = OtherVar.getContext();
+                        if(otherScope.isLexicalBlock()){
+                            /* find the subprogram that contains this basic block recursively */
+                            while(!otherScope.isSubprogram()){
+                                otherScope = DILexicalBlock(otherScope).getContext();
+                            }
+                        }
+                        if(otherScope.isSubprogram()){
+                            if(!strcmp(Var.getName().data(), OtherVar.getName().data())){
+                                if(DIGV == OtherDIGV){
+                                    break;
+                                }
+                                count++;
+                            }
+                        }
+                    }
+                }
+
+                std::stringstream stm;
+                if(count > 0){
+                    stm << "." << count;
+                }
+                countStr = StringRef(*new std::string(stm.str()));
+
+            }else{
+                /* static global variable */
+                funcName = "";
+                countStr = "";
+            }
+
+            std::stringstream stm;
+            stm << Var.getName().data() << "." << getModuleHash(Var, baseDir, funcName) << countStr.data();
+            return StringRef(*new std::string(stm.str()));
+
+        }else{
+            /* global variable */
+            return Var.getName();
+        }
+    }else{
+        /* llvm .str variables and assembly */
+        if(DIGVP) *DIGVP = NULL;
+        return GV->getName();
+    }
+}
+
+StringRef MagicUtil::getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP) {
+    static DIVariable Var;
+    const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(V);
+    if(DDI && DDI != (const DbgDeclareInst *) -1){
+        Var = DIVariable(cast<MDNode>(DDI->getVariable()));
+        if(DIVP) *DIVP = &Var;
+
+        int count = 0;
+
+        Function *F = V->getParent()->getParent();
+        for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
+            Instruction *inst = &(*it);
+            if (DbgDeclareInst *OtherDDI = dyn_cast<DbgDeclareInst>(inst)){
+                DIVariable otherVar(cast<MDNode>(OtherDDI->getVariable()));
+                if(!strcmp(Var.getName().data(), otherVar.getName().data())){
+                    if(OtherDDI == DDI){
+                        break;
+                    }
+                    count++;
+                }
+            }
+        }
+
+        std::stringstream stm;
+        stm << Var.getName().data();
+        if(count > 0){
+            stm << "." << count;
+        }
+        return StringRef(*new std::string(stm.str()));
+    }else{
+        if(DIVP) *DIVP = NULL;
+        return V->getName();
+    }
+}
+
+StringRef MagicUtil::getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP, const std::string &baseDir) {
+    static DISubprogram Func;
+    Value *DIF = Backports::findDbgSubprogramDeclare(F);
+    if(DIF) {
+        Func = DISubprogram(cast<MDNode>(DIF));
+        if(DISP) *DISP = &Func;
+        if(F->getLinkage() == GlobalValue::InternalLinkage){
+            std::stringstream stm;
+            stm << Func.getName().data() << "." << getModuleHash(Func, baseDir);
+            return StringRef(*new std::string(stm.str()));
+        }else{
+            return Func.getName();
+        }
+    }else{
+        /* assembly */
+        if(DISP) *DISP = NULL;
+        return F->getName();
+    }
+}
+
+void MagicUtil::putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV) {
+    std::map<const std::string, GlobalVariable*>::iterator it;
+    it = stringRefCache.find(str);
+    if(it == stringRefCache.end()) {
+        stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, GV));
+    }
+}
+
+Constant* MagicUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
+    return PassUtil::getGetElementPtrConstant(constant, indexes);
+}
+
+GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
+    return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertBefore);
+}
+
+GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+    return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertAtEnd);
+}
+
+CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
+    return PassUtil::createCallInstruction(F, args, NameStr, InsertBefore);
+}
+
+CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
+    return PassUtil::createCallInstruction(F, args, NameStr, InsertAtEnd);
+}
+
+Function* MagicUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
+    return PassUtil::getIntrinsicFunction(M, id, types, size);
+}
+
+GlobalVariable *MagicUtil::getStringRef(Module &M, const std::string &str) {
+    std::map<const std::string, GlobalVariable*>::iterator it;
+    GlobalVariable *stringRef = NULL;
+    bool debug = false;
+
+    it = stringRefCache.find(str);
+    if(it != stringRefCache.end()) {
+        if(debug) magicUtilLog("*** getStringRef: cache hit for " << str);
+        stringRef = it->second;
+    }
+    if(stringRef == NULL) {
+       stringRef = PassUtil::getStringGlobalVariable(M, str, MAGIC_HIDDEN_STR_PREFIX, MAGIC_STATIC_VARS_SECTION_RO);
+        stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, stringRef));
+    }
+
+     return stringRef;
+ }
+
+
+GlobalVariable *MagicUtil::getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant) {
+    static std::map<std::vector<int>, GlobalVariable*> arrayRefCache;
+    std::map<std::vector<int>, GlobalVariable*>::iterator it;
+    static std::vector<int> defInitilizer;
+
+    //construct an appropriate initializer if we do not have one
+    if(!arr) {
+        arr = &defInitilizer;
+        arr->clear();
+        for(unsigned i=0;i<arrSize;i++) arr->push_back(0);
+    }
+    assert(arrSize == arr->size());
+
+    //cache lookup
+    if(isConstant) {
+        it = arrayRefCache.find(*arr);
+        if(it != arrayRefCache.end()) {
+            return it->second;
+        }
+    }
+
+    //create a constant internal array reference
+    std::vector<Constant*> arrayElems;
+    for(unsigned i=0;i<arr->size();i++) {
+        arrayElems.push_back(ConstantInt::get(M.getContext(), APInt(32, (*arr)[i], 10)));
+    }
+    ArrayType* arrayTy = ArrayType::get(IntegerType::get(M.getContext(), 32), arr->size());
+    Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+    //create the global variable and record it in the module
+    GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+        GlobalValue::InternalLinkage, arrayValue,
+        MAGIC_HIDDEN_ARRAY_PREFIX);
+    MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+    M.getGlobalList().push_back(arrayRef);
+
+    //populate cache
+    if(isConstant) {
+        arrayRefCache.insert(std::pair<std::vector<int>, GlobalVariable*>(*arr, arrayRef));
+    }
+
+    return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant) {
+    static std::map<std::vector<std::string>, GlobalVariable*> arrayRefCache;
+    std::map<std::vector<std::string>, GlobalVariable*>::iterator it;
+    static std::vector<std::string> defInitilizer;
+    //construct an appropriate initializer if we do not have one
+    if(!arr) {
+        arr = &defInitilizer;
+        arr->clear();
+        for(unsigned i=0;i<arrSize;i++) arr->push_back("");
+    }
+    assert(arrSize == arr->size());
+
+    //cache lookup
+    if(isConstant) {
+        it = arrayRefCache.find(*arr);
+        if(it != arrayRefCache.end()) {
+            return it->second;
+        }
+    }
+
+    //create a constant internal array reference
+    std::vector<Constant*> arrayElems;
+    std::vector<Value*> arrayIndexes;
+    arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+    arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+    for(unsigned i=0;i<arr->size();i++) {
+        arrayElems.push_back(getGetElementPtrConstant(getStringRef(M, (*arr)[i]), arrayIndexes));
+    }
+    ArrayType* arrayTy = ArrayType::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0), arr->size());
+    Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+    //create the global variable and record it in the module
+    GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+        GlobalValue::InternalLinkage, arrayValue,
+        MAGIC_HIDDEN_ARRAY_PREFIX);
+    MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+    M.getGlobalList().push_back(arrayRef);
+
+    //populate cache
+    if(isConstant) {
+        arrayRefCache.insert(std::pair<std::vector<std::string>, GlobalVariable*>(*arr, arrayRef));
+    }
+
+    return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant) {
+    static std::map<std::vector<Constant*>, GlobalVariable*> arrayRefCache;
+    std::map<std::vector<Constant*>, GlobalVariable*>::iterator it;
+    assert(arrayElems.size() > 0);
+
+    //cache lookup
+    if(isConstant) {
+        it = arrayRefCache.find(arrayElems);
+        if(it != arrayRefCache.end()) {
+            return it->second;
+        }
+    }
+
+    //create a constant internal array reference
+    ArrayType* arrayTy = ArrayType::get(arrayElems[0]->getType(), arrayElems.size());
+    Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
+
+    //create the global variable and record it in the module
+    GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
+        GlobalValue::InternalLinkage, arrayValue,
+        MAGIC_HIDDEN_ARRAY_PREFIX);
+    MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+    M.getGlobalList().push_back(arrayRef);
+
+    //populate cache
+    if(isConstant) {
+        arrayRefCache.insert(std::pair<std::vector<Constant*>, GlobalVariable*>(arrayElems, arrayRef));
+    }
+
+    return arrayRef;
+}
+
+GlobalVariable *MagicUtil::getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray) {
+    int numTypeIndexes = globalTypeIndexes.size();
+    TYPECONST StructType* magicTypeStructTy = (TYPECONST StructType*) ((TYPECONST ArrayType*)magicTypeArray->getType()->getElementType())->getElementType();
+    ArrayType* typeIndexesArrTy = ArrayType::get(PointerType::get(magicTypeStructTy, 0), numTypeIndexes+1);
+    std::vector<Constant*> arrayElems;
+    for(int i=0;i<numTypeIndexes;i++) {
+        std::vector<Value*> magicTypeArrayIndexes;
+        magicTypeArrayIndexes.clear();
+        magicTypeArrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
+        magicTypeArrayIndexes.push_back(globalTypeIndexes[i]);
+        Constant* typePtr = getGetElementPtrConstant(magicTypeArray, magicTypeArrayIndexes);
+        arrayElems.push_back(typePtr);
+    }
+    arrayElems.push_back(ConstantPointerNull::get(PointerType::get(magicTypeStructTy, 0))); //NULL-terminated array
+
+    //create the global variable and record it in the module
+    Constant *arrayValue = ConstantArray::get(typeIndexesArrTy, arrayElems);
+    GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), true,
+        GlobalValue::InternalLinkage, arrayValue,
+        MAGIC_HIDDEN_ARRAY_PREFIX);
+    MagicUtil::setGlobalVariableSection(arrayRef, MAGIC_STATIC_VARS_SECTION_RO);
+    M.getGlobalList().push_back(arrayRef);
+
+    return arrayRef;
+}
+
+GlobalVariable* MagicUtil::getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant) {
+    Constant *intValue = ConstantInt::get(M.getContext(), APInt(32, value, 10));
+
+    //create the global variable and record it in the module
+    GlobalVariable *GV = new GlobalVariable(intValue->getType(), isConstant,
+        GlobalValue::LinkOnceAnyLinkage, intValue, name);
+    MagicUtil::setGlobalVariableSection(GV, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
+    M.getGlobalList().push_back(GV);
+
+    return GV;
+}
+
+GlobalVariable* MagicUtil::getShadowRef(Module &M, GlobalVariable *GV) {
+    //create the shadow global variable and record it in the module
+    TYPECONST Type* type = GV->getType()->getElementType();
+    GlobalVariable *SGV = new GlobalVariable(type, GV->isConstant(),
+                                          GlobalValue::InternalLinkage, 0,
+                                          MAGIC_SHADOW_VAR_PREFIX + GV->getName());
+    SGV->setInitializer(Constant::getNullValue(type));
+    MagicUtil::setGlobalVariableSection(SGV, GV->isConstant() ? MAGIC_SHADOW_VARS_SECTION_RO : MAGIC_SHADOW_VARS_SECTION_DATA);
+    M.getGlobalList().push_back(SGV);
+
+    if(!GV->hasInitializer()) {
+        magicUtilLog("Shadowing for extern variable: " << GV->getName());
+    }
+    if(GV->isConstant()) {
+        magicUtilLog("Shadowing for constant variable: " << GV->getName());
+    }
+
+    return SGV;
+}
+
+Value* MagicUtil::getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* var, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames) {
+    //lookup field index
+    int structFieldIndex;
+    Value *varPtr;
+    for(structFieldIndex=0; structFieldName.compare(structFieldNames[structFieldIndex]) != 0; structFieldIndex++) {}
+
+    if(arrayIndex) {
+        //get array ptr
+        std::vector<Value*> arrayIndexes;
+        arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
+        arrayIndexes.push_back(arrayIndex);
+        varPtr = createGetElementPtrInstruction(var, arrayIndexes, "", InsertBefore);
+    }
+    else {
+       varPtr = var;
+    }
+
+    //get struct field ptr
+    std::vector<Value*> structFieldIndexes;
+    structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
+    structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, structFieldIndex, 10)));
+    Instruction* structFieldPtr = createGetElementPtrInstruction(varPtr, structFieldIndexes, "", InsertBefore);
+
+    return structFieldPtr;
+}
+
+Value* MagicUtil::getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName) {
+    static std::string structFieldNames[] = { MAGIC_SSTRUCT_FIELDS };
+    return getMagicStructFieldPtr(M, InsertBefore, magicArray, magicArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName) {
+    static std::string structFieldNames[] = { MAGIC_TSTRUCT_FIELDS };
+    return getMagicStructFieldPtr(M, InsertBefore, magicTypeArray, magicTypeArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName) {
+    static std::string structFieldNames[] = { MAGIC_FSTRUCT_FIELDS };
+    return getMagicStructFieldPtr(M, InsertBefore, magicFunctionArray, magicFunctionArrayIndex, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName) {
+    static std::string structFieldNames[] = { MAGIC_RSTRUCT_FIELDS };
+    return getMagicStructFieldPtr(M, InsertBefore, magicVar, NULL, structFieldName, structFieldNames);
+}
+
+Value* MagicUtil::getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName) {
+    static std::string structFieldNames[] = { MAGIC_DSTRUCT_FIELDS };
+    return getMagicStructFieldPtr(M, InsertBefore, magicDsindexArray, magicDsindexArrayIndex, structFieldName, structFieldNames);
+}
+
+Constant* MagicUtil::getArrayPtr(Module &M, GlobalVariable* array) {
+    //indexes for array
+    static std::vector<Value*> arrayIndexes;
+    if(arrayIndexes.empty()) {
+        arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
+        arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[0]
+    }
+
+    //get array ptr
+    Constant* arrayPtr = getGetElementPtrConstant(array, arrayIndexes);
+
+    return arrayPtr;
+}
+
+void MagicUtil::insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align) {
+    bool useMemCpyIntrinsics = false;
+    Function *MemCpy = M.getFunction("memcpy");
+    if(!MemCpy) {
+        TYPECONST Type *ArgTys[1] = { IntegerType::getInt32Ty(M.getContext()) };
+        MemCpy = getIntrinsicFunction(M, Intrinsic::memcpy, ArgTys, 1);
+        useMemCpyIntrinsics = true;
+    }
+    else {
+        MemCpy = (Function*) M.getOrInsertFunction(MAGIC_MEMCPY_FUNC_NAME, MemCpy->getFunctionType());
+    }
+
+    // Insert the memcpy instruction
+    std::vector<Value*> MemCpyArgs;
+    MemCpyArgs.push_back(Dst);
+    MemCpyArgs.push_back(Src);
+    MemCpyArgs.push_back(Len);
+    if(useMemCpyIntrinsics) {
+        MemCpyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, Align, 10)));
+    }
+    createCallInstruction(MemCpy, MemCpyArgs, "", InsertBefore);
+}
+
+void MagicUtil::insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy) {
+    //get type and type size
+    TYPECONST Type *GVType = GV->getType()->getElementType();
+    bool isPrimitiveOrPointerType = !GVType->isAggregateType();
+
+    //no need for memcpy for primitive types or pointer types
+    if(isPrimitiveOrPointerType && !forceMemcpy) {
+        LoadInst* primitiveValue = new LoadInst(GV, "", false, InsertBefore);
+        new StoreInst(primitiveValue, SGV, false, InsertBefore);
+        return;
+    }
+
+    //cast pointers to match memcpy prototype
+    PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+    Constant* varAddress = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
+    Constant* varShadowAddress = ConstantExpr::getCast(Instruction::BitCast, SGV, voidPointerType);
+
+    //insert the memcpy instruction
+    MagicUtil::insertMemcpyInst(M, InsertBefore, varShadowAddress, varAddress, ConstantInt::get(M.getContext(), APInt(32, GVSize, 10)), 0);
+}
+
+Function* MagicUtil::getCalledFunctionFromCS(const CallSite &CS) {
+    assert(CS.getInstruction());
+    Function *function = CS.getCalledFunction();
+    if(function) {
+        return function;
+    }
+
+    //handle the weird case of bitcasted function call
+    //IMPORTANT! function may still be null, if it's an indirect call
+    ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue());
+    if (CE) {
+        assert(CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!");
+        function = dyn_cast<Function>(CE->getOperand(0));
+        assert(function);
+    } else {
+        errs() << "Warning! Indirect call encountered!\n";
+    }
+
+    return function;
+}
+
+void MagicUtil::replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset, bool removeUnusedFunction) {
+    SmallVector< std::pair< unsigned, MDNode * >, 8> MDs;
+    originalInst->getAllMetadata(MDs);
+    for(unsigned i=0;i<MDs.size();i++) {
+        newInst->setMetadata(MDs[i].first, MDs[i].second);
+    }
+    CallSite CS = MagicUtil::getCallSiteFromInstruction(originalInst);
+    assert(CS);
+    CallingConv::ID CC = CS.getCallingConv();
+    Function *originalFunction = getCalledFunctionFromCS(CS);
+    newInst->setCallingConv(CC);
+    ATTRIBUTE_SET_TY NewAttrs = PassUtil::remapCallSiteAttributes(CS, argOffset);
+    newInst->setAttributes(NewAttrs);
+
+    originalInst->replaceAllUsesWith(newInst);
+
+    // If the old instruction was an invoke, add an unconditional branch
+    // before the invoke, which will become the new terminator.
+    if (InvokeInst *II = dyn_cast<InvokeInst>(originalInst))
+      BranchInst::Create(II->getNormalDest(), originalInst);
+
+    // Delete the old call site
+    originalInst->eraseFromParent();
+
+    // When asked, remove the original function when nobody uses it any more.
+    if(removeUnusedFunction && originalFunction->use_empty()) {
+        originalFunction->eraseFromParent();
+    }
+}
+
+std::vector<Function*> MagicUtil::getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag) {
+    std::vector<Function*> globalVariableShadowFunctions;
+    for(int i=0;i<magicArraySize;i++) {
+        Function* func = getGlobalVariableShadowFunction(M, globalVariables[i], shadowGlobalVariables[i], globalVariableSizes[i], magicArray, i, forceShadow, setDirtyFlag);
+        globalVariableShadowFunctions.push_back(func);
+    }
+
+    return globalVariableShadowFunctions;
+}
+
+Function* MagicUtil::getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag) {
+    static Constant* magicStateDirty = ConstantInt::get(M.getContext(), APInt(32, MAGIC_STATE_DIRTY, 10));
+    static Function* shadowFunc = NULL;
+    ConstantInt* magicArrayIndexConst = ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10));
+
+    //determine name
+    std::string name(MAGIC_SHADOW_FUNC_PREFIX);
+    name.append("_");
+    if(forceShadow) {
+        name.append("force_");
+    }
+    if(setDirtyFlag) {
+        name.append("setdf_");
+    }
+    name.append(GV->getName());
+
+    //create function
+    std::vector<TYPECONST Type*>shadowFuncArgs;
+    FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
+    shadowFunc = Function::Create(shadowFuncType, GlobalValue::InternalLinkage, name, &M);
+    shadowFunc->setCallingConv(CallingConv::C);
+
+    //create blocks
+    BasicBlock* label_entry = BasicBlock::Create(M.getContext(), "entry",shadowFunc,0);
+    BasicBlock* label_shadow = BasicBlock::Create(M.getContext(), "shadow",shadowFunc,0);
+    BasicBlock* label_return = BasicBlock::Create(M.getContext(), "return",shadowFunc,0);
+    BranchInst::Create(label_shadow, label_entry);
+    BranchInst::Create(label_return, label_shadow);
+    Instruction* entryTerm = label_entry->getTerminator();
+    Instruction* shadowTerm = label_shadow->getTerminator();
+
+    if(!forceShadow || setDirtyFlag) {
+        //get flags
+        Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, entryTerm, magicArray, magicArrayIndexConst, MAGIC_SSTRUCT_FIELD_FLAGS);
+        LoadInst* varFlags = new LoadInst(structFlagsField, "", false, entryTerm);
+
+        //when not forcing, don't shadow if dirty is already set
+        if(!forceShadow) {
+            BinaryOperator* andedVarFlags = BinaryOperator::Create(Instruction::And, varFlags, magicStateDirty, "", entryTerm);
+            ICmpInst* flagsCmp = new ICmpInst(entryTerm, ICmpInst::ICMP_EQ, andedVarFlags, ConstantInt::get(M.getContext(), APInt(32, 0, 10)), "");
+            BranchInst::Create(label_shadow, label_return, flagsCmp, entryTerm);
+            entryTerm->eraseFromParent();
+        }
+
+        //set the dirty flag for the variable
+        if(setDirtyFlag) {
+            BinaryOperator* oredVarFlags = BinaryOperator::Create(Instruction::Or, varFlags, magicStateDirty, "", shadowTerm);
+            new StoreInst(oredVarFlags, structFlagsField, false, shadowTerm);
+        }
+    }
+
+    //perform a memory copy from the original variable to the shadow variable
+    MagicUtil::insertCopyInst(M, shadowTerm, GV, SGV, GVSize, /* forceMemcpy */ false);
+
+    ReturnInst::Create(M.getContext(), label_return);
+
+    return shadowFunc;
+}
+
+void MagicUtil::insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore) {
+    Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, InsertBefore, magicArray, ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
+    new StoreInst(ConstantInt::get(M.getContext(), APInt(32, 0, 10)), structFlagsField, false, InsertBefore);
+}
+
+void MagicUtil::insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore) {
+    static Function* shadowFunc = NULL;
+    PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
+
+    //create function
+    if(!shadowFunc) {
+            std::vector<TYPECONST Type*>shadowFuncArgs;
+            shadowFuncArgs.push_back(voidPointerType);
+            FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
+            shadowFunc = Function::Create(shadowFuncType, GlobalValue::ExternalLinkage, MAGIC_LAZY_CHECKPOINT_SHADOW_TAG, &M);
+            shadowFunc->setCallingConv(CallingConv::C);
+    }
+
+    //shadow global variable
+    std::vector<Value*> args;
+    args.push_back(new BitCastInst(GV, voidPointerType, "", InsertBefore));
+    CallInst *callInst = createCallInstruction(shadowFunc, args, "", InsertBefore);
+    callInst->setCallingConv(CallingConv::C);
+}
+
+bool MagicUtil::isShadowTag(Instruction *inst) {
+    if(dyn_cast<CallInst>(inst)) {
+            CallInst *callInst = dyn_cast<CallInst>(inst);
+            Function *function = callInst->getCalledFunction();
+            if(function == NULL) {
+                    return false;
+            }
+            std::string funcName = function->getName();
+            if(!funcName.compare(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG)) {
+                    return true;
+            }
+    }
+    return false;
+}
+
+GlobalVariable* MagicUtil::getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove) {
+    CallSite CS = MagicUtil::getCallSiteFromInstruction(inst);
+    assert(CS.arg_size() == 1);
+    instructionsToRemove.push_back(inst);
+    CallSite::arg_iterator AI = CS.arg_begin();
+    Value *ActualArg = *AI;
+
+    while(true) {
+        BitCastInst *castInst = dyn_cast<BitCastInst>(ActualArg);
+        ConstantExpr *castExpr = dyn_cast<ConstantExpr>(ActualArg);
+        if(castInst) {
+            assert(castInst->getNumOperands() == 1);
+            ActualArg = castInst->getOperand(0);
+            instructionsToRemove.push_back(castInst);
+        }
+        else if(castExpr) {
+            //assert(castExpr->getNumOperands() == 1);
+            ActualArg = castExpr->getOperand(0);
+        }
+        else {
+            break;
+        }
+    }
+
+    GlobalVariable *GV = dyn_cast<GlobalVariable>(ActualArg);
+    if(GV == NULL) {
+        magicUtilLog("Weird ActualArg: " << *ActualArg);
+    }
+    assert(GV != NULL);
+
+    return GV;
+}
+
+void MagicUtil::cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove) {
+    int i=0;
+
+    for(i =0;i<(int)instructionsToRemove.size();i++) {
+        Instruction *inst = instructionsToRemove[i];
+        inst->eraseFromParent();
+    }
+    Function* func = M.getFunction(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG);
+    if(func && func->getNumUses() == 0) {
+        func->eraseFromParent();
+    }
+}
+
+bool MagicUtil::hasAddressTaken(const GlobalValue *GV, bool includeMembers) {
+  //Most of the code taken from LLVM's SCCP.cpp
+
+  // Delete any dead constantexpr klingons.
+  GV->removeDeadConstantUsers();
+
+  std::vector<const User*> sourceUsers;
+  sourceUsers.push_back(GV);
+  if(includeMembers && isa<GlobalVariable>(GV)) {
+      for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
+          UI != E; ++UI) {
+          const User *U = *UI;
+          const ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
+          if(isa<GetElementPtrInst>(U)) {
+              sourceUsers.push_back(U);
+          }
+          else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+              sourceUsers.push_back(U);
+          }
+      }
+  }
+
+  for(unsigned i=0;i<sourceUsers.size();i++) {
+      for (Value::const_use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
+           UI != E; ++UI) {
+        const User *U = *UI;
+        if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
+          if (SI->getOperand(0) == sourceUsers[i] || SI->isVolatile())
+            return true;  // Storing addr of sourceUsers[i].
+        } else if (isa<InvokeInst>(U) || isa<CallInst>(U)) {
+          // Make sure we are calling the function, not passing the address.
+          ImmutableCallSite CS(cast<Instruction>(U));
+          if (!CS.isCallee(UI))
+            return true;
+        } else if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
+          if (LI->isVolatile())
+            return true;
+        } else if (isa<BlockAddress>(U)) {
+          // blockaddress doesn't take the address of the function, it takes addr
+          // of label.
+        } else {
+          return true;
+        }
+      }
+  }
+  return false;
+}
+
+bool MagicUtil::lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet) {
+  //Similar to hasAddressTaken above, but we look for values
+
+  if(!isa<IntegerType>(GV->getType()->getElementType())) {
+      //integers is all we are interested in
+      return false;
+  }
+  if(!GV->hasInitializer()) {
+      //external variable
+      return false;
+  }
+
+  // Delete any dead constantexpr klingons.
+  GV->removeDeadConstantUsers();
+
+  std::set<int> set;
+  for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end();
+      UI != E; ++UI) {
+      const User *U = *UI;
+      if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
+          if (SI->getOperand(1) == GV) {
+             Value *value = SI->getOperand(0);
+             if(ConstantInt *intValue = dyn_cast<ConstantInt>(value)) {
+                 set.insert(intValue->getSExtValue());
+             }
+             else {
+                 return false;
+             }
+          }
+      }
+  }
+  const Constant *constant = GV->getInitializer();
+  if(const ConstantInt *intConstant = dyn_cast<const ConstantInt>(constant)) {
+      set.insert(intConstant->getSExtValue());
+  }
+  else {
+      return false;
+  }
+
+  assert(set.size() > 0);
+  valueSet.push_back(set.size()); //push length as the first value
+  for(std::set<int>::iterator it=set.begin() ; it != set.end(); it++) {
+      valueSet.push_back(*it);
+  }
+
+  return true;
+}
+
+Value* MagicUtil::getStringOwner(GlobalVariable *GV)
+{
+  //Similar to hasAddressTaken above, but we look for string owners
+  assert(GV && GV->isConstant());
+
+  // Skip emtpy strings.
+  if(GV->hasInitializer() && GV->getInitializer()->isNullValue()) {
+      return NULL;
+  }
+
+  // Delete any dead constantexpr klingons.
+  GV->removeDeadConstantUsers();
+
+  std::vector<User*> sourceUsers;
+  sourceUsers.push_back(GV);
+  for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
+      UI != E; ++UI) {
+      User *U = *UI;
+      ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
+      if(isa<GetElementPtrInst>(U)) {
+          sourceUsers.push_back(U);
+      }
+      else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
+          sourceUsers.push_back(U);
+      }
+  }
+
+  Value *stringOwner = NULL;
+  for(unsigned i=0;i<sourceUsers.size();i++) {
+      for (Value::use_iterator UI = sourceUsers[i]->use_begin(), E = sourceUsers[i]->use_end();
+           UI != E; ++UI) {
+          User *U = *UI;
+          Value *V = U;
+          if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
+              V = SI->getPointerOperand();
+          }
+          if(isa<GlobalVariable>(V) || isa<AllocaInst>(V)) {
+              if(stringOwner != NULL && stringOwner != V) {
+                  //no owner in the ambiguous cases
+                  return NULL;
+              }
+              stringOwner = V;
+          }
+      }
+  }
+
+  return stringOwner;
+}
+
+Instruction* MagicUtil::getFirstNonAllocaInst(Function *F, bool skipAllocaPoint)
+{
+  Instruction *I = NULL;
+  if (skipAllocaPoint) {
+      PassUtil::getAllocaInfo(F, NULL, &I);
+  }
+  else {
+      PassUtil::getAllocaInfo(F, &I, NULL);
+  }
+  assert(I);
+  return I;
+}
+
+void MagicUtil::setGlobalVariableSection(GlobalVariable *GV, const std::string &section)
+{
+  if(GV->isThreadLocal()) {
+      return;
+  }
+
+  GV->setSection(section);
+}
+
+bool MagicUtil::getCallAnnotation(Module &M, const CallSite &CS, int *annotation)
+{
+  static GlobalVariable *magicAnnotationVar = NULL;
+  bool instFound = false;
+  bool annotationFound = false;
+  if(!magicAnnotationVar) {
+      magicAnnotationVar = M.getNamedGlobal(MAGIC_CALL_ANNOTATION_VAR_NAME);
+      assert(magicAnnotationVar);
+  }
+  Instruction *I = CS.getInstruction();
+  if(!I) {
+      return false;
+  }
+  BasicBlock *parent = I->getParent();
+  for (BasicBlock::iterator i = parent->begin(), e = parent->end(); i != e; ++i) {
+      Instruction *inst = i;
+      if(inst != I && !instFound) {
+          continue;
+      }
+      instFound = true;
+      if(inst == I) {
+          continue;
+      }
+      if(StoreInst *SI = dyn_cast<StoreInst>(inst)) {
+          if(SI->getOperand(1) == magicAnnotationVar) {
+              ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(0));
+              assert(CI && "Bad call annotation!");
+              annotationFound = true;
+              *annotation = CI->getSExtValue();
+              break;
+          }
+      }
+      else if(isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
+          break;
+      }
+  }
+  return annotationFound;
+}
+
+bool MagicUtil::getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation)
+{
+  std::string GVName = GV->getName();
+  GlobalVariable *annotationGV = M.getNamedGlobal(MAGIC_VAR_ANNOTATION_PREFIX_NAME + GVName);
+  if(!annotationGV || !annotationGV->hasInitializer()) {
+      return false;
+  }
+  ConstantInt* annotationValue = dyn_cast<ConstantInt>(annotationGV->getInitializer());
+  if(!annotationValue) {
+      return false;
+  }
+  *annotation = (int) annotationValue->getSExtValue();
+  return true;
+}
+
+CallSite MagicUtil::getCallSiteFromInstruction(Instruction *I)
+{
+  return PassUtil::getCallSiteFromInstruction(I);
+}
+
+AllocaInst* MagicUtil::getAllocaInstFromArgument(Argument *argument)
+{
+  Function *parent = argument->getParent();
+  std::string targetString = argument->getName().str() + "_addr";
+  std::string targetString2 = argument->getName().str() + ".addr";
+  StringRef targetName(targetString);
+  StringRef targetName2(targetString2);
+  for (inst_iterator it = inst_begin(parent), et = inst_end(parent); it != et; ++it) {
+      AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
+      if(!AI) {
+          break;
+      }
+      if(AI->getName().startswith(targetName) || AI->getName().startswith(targetName2)) {
+          return AI;
+      }
+  }
+
+  return NULL;
+}
+
+// searches for the specified function in module symbol table assuming that its name has been mangled
+// returns NULL if the function has not been found
+Function* MagicUtil::getMangledFunction(Module &M, StringRef functionName)
+{
+       Function *F = NULL;
+       char* outbuf;
+       const char* functionNameString = functionName.data();
+       int status;
+       for (Module::iterator it = M.begin(); it != M.end(); ++it) {
+               StringRef mangledName = (*it).getName();
+               outbuf = abi::__cxa_demangle(mangledName.data(), NULL, NULL, &status);
+               if (status == -2) {
+                       continue; // mangledName is not a valid name under the C++ ABI mangling rules
+               }
+               assert(status == 0 && outbuf && "Error when trying to demangle a function name.");
+               // testing whether this is the function we are looking for
+               // the unmangled name is similar to a function prototype eg my_func(int, void*, int)
+               char* pos = strstr(outbuf, functionNameString);
+               if (!pos) {
+                       free(outbuf);
+                       continue;
+               }
+               // function names can only contain alpha-numeric characters and '_'
+               // if the unmangled name refers to the target function, then that substring should not
+               // be surrounded by characters allowed in a function name
+               // (to exclude cases such as myfunc vs _myfunc vs myfunc2)
+               if (pos > outbuf) {
+                       if (isalnum(*(pos - 1)) || (*(pos - 1) == '_')) {
+                               free(outbuf);
+                               continue;
+                       }
+               }
+               if (strlen(pos) > strlen(functionNameString)) {
+                       if (isalnum(*(pos + strlen(functionNameString))) || (*(pos + strlen(functionNameString)) == '_')) {
+                               free(outbuf);
+                               continue;
+                       }
+               }
+               F = it;
+               free(outbuf);
+               break;
+       }
+
+       return F;
+}
+
+Function* MagicUtil::getFunction(Module &M, StringRef functionName)
+{
+       Function* F = M.getFunction(functionName);
+       if (!F) {
+               F = MagicUtil::getMangledFunction(M, functionName);
+       }
+       return F;
+}
+
+// can Type1 be represented as Type2 (with no precision loss)
+bool MagicUtil::isCompatibleType(const Type* Type1, const Type* Type2)
+{
+       if (Type1 == Type2) {
+               return true;
+       }
+       if (Type1->isIntegerTy() && Type2->isIntegerTy()) {
+               if (((const IntegerType*)Type1)->getBitWidth() <= ((const IntegerType*)Type2)->getBitWidth()) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+// inserts an inlined call to the pre-hook function before any other instruction is executed
+// it can forward (some of) the original function's parameters and additional trailing arguments
+void MagicUtil::inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs)
+{
+       std::vector<Value*> callArgs;
+       assert(preHookFunction->arg_size() == argsMapping.size() + trailingArgs.size() &&
+                       "The number of parameter values specified for the pre-hook function does not match the signature of the function.");
+       for (std::vector<unsigned>::iterator it = argsMapping.begin(); it != argsMapping.end(); it++) {
+               callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
+       }
+       for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
+               callArgs.push_back(*it);
+       }
+       // insert the call after the alloca instructions so that they remain for sure in the entry block
+       Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(function);
+       for (unsigned i = 0; i < callArgs.size(); ++i) {
+               TYPECONST Type* ArgType = callArgs[i]->getType();
+               TYPECONST Type* ParamType = preHookFunction->getFunctionType()->getParamType(i);
+
+               if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
+                       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 CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
+                       callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", FirstInst);
+               }
+       }
+
+       CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(preHookFunction, callArgs, "", FirstInst);
+       InlineFunctionInfo IFI;
+       InlineFunction(WrapperFuncCall, IFI);
+}
+
+// inserts an inlined call to the post-hook function before all return instructions
+// forwarded arguments from the first function come first, followed by the trailing ones
+// use offsets > 0 for function parameter mappings, and 0 for the return value of the function
+void MagicUtil::inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs)
+{
+       std::vector<CallInst*> wrapperCalls;
+       assert(postHookFunction->arg_size() == mapping.size() + trailingArgs.size()
+                       && "The number of parameter values specified for the post-hook function does not match the signature of the function.");
+
+       for (Function::iterator BI = function->getBasicBlockList().begin(); BI != function->getBasicBlockList().end(); ++BI) {
+               ReturnInst *RetInst = dyn_cast<ReturnInst>(BI->getTerminator());
+               if (RetInst) {
+                       std::vector<Value*> callArgs;
+                       for (std::vector<unsigned>::iterator it = mapping.begin(); it != mapping.end(); it++) {
+                               if (*it > 0) {
+                                       callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
+                               } else {
+                                       callArgs.push_back(RetInst->getReturnValue());
+                               }
+                       }
+                       for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
+                               callArgs.push_back(*it);
+                       }
+                       for (unsigned i = 0; i < callArgs.size(); i++) {
+                               TYPECONST Type* ArgType = callArgs[i]->getType();
+                               TYPECONST Type* ParamType = postHookFunction->getFunctionType()->getParamType(i);
+
+                               if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
+                                       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 CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
+                                       callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", RetInst);
+                               }
+                       }
+                       CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(postHookFunction, callArgs, "", RetInst);
+                       wrapperCalls.push_back(WrapperFuncCall);
+               }
+       }
+       for (std::vector<CallInst*>::iterator it = wrapperCalls.begin(); it != wrapperCalls.end(); ++it) {
+               InlineFunctionInfo IFI;
+               InlineFunction(*it, IFI);
+       }
+}
+
+int MagicUtil::getPointerIndirectionLevel(const Type* type)
+{
+       int level = 0;
+       if (const PointerType* ptr_type = dyn_cast<PointerType>(type)) {
+               while (ptr_type) {
+                       level++;
+                       ptr_type = dyn_cast<PointerType>(ptr_type->getElementType());
+               }
+       }
+
+       return level;
+}
+
+Value* MagicUtil::getFunctionParam(Function* function, unsigned index)
+{
+       if (index >= function->arg_size()) {
+               return NULL;
+       }
+       Function::arg_iterator AI = function->arg_begin();
+       while (index --> 0) {
+               AI++;
+       }
+       return AI;
+}
+
+bool MagicUtil::isLocalConstant(Module &M, GlobalVariable *GV)
+{
+       if (!GV->isConstant()) {
+               return false;
+       }
+       if (GV->getName().endswith(".v")) {
+               return true;
+       }
+       std::pair<StringRef, StringRef> stringPair = GV->getName().split('.');
+       StringRef functionName = stringPair.first;
+       if (!functionName.compare("") || M.getFunction(functionName) == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
+}
diff --git a/minix/llvm/passes/magic/support/SmartType.cpp b/minix/llvm/passes/magic/support/SmartType.cpp
new file mode 100644 (file)
index 0000000..281f204
--- /dev/null
@@ -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;
+
+}
diff --git a/minix/llvm/passes/magic/support/TypeUtil.cpp b/minix/llvm/passes/magic/support/TypeUtil.cpp
new file mode 100644 (file)
index 0000000..bab861c
--- /dev/null
@@ -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;
+
+}
diff --git a/minix/llvm/passes/magic/support/VariableRefs.cpp b/minix/llvm/passes/magic/support/VariableRefs.cpp
new file mode 100644 (file)
index 0000000..92bec82
--- /dev/null
@@ -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;
+}
+
+}