diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/CMakeLists.txt | 5 | ||||
-rw-r--r-- | runtime/libprofile/CMakeLists.txt | 19 | ||||
-rw-r--r-- | runtime/libprofile/CommonProfiling.c | 4 | ||||
-rw-r--r-- | runtime/libprofile/GCDAProfiling.c | 152 | ||||
-rw-r--r-- | runtime/libprofile/Makefile | 4 | ||||
-rw-r--r-- | runtime/libprofile/OptimalEdgeProfiling.c | 2 | ||||
-rw-r--r-- | runtime/libprofile/PathProfiling.c | 21 | ||||
-rw-r--r-- | runtime/libprofile/libprofile.exports | 5 |
8 files changed, 203 insertions, 9 deletions
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt new file mode 100644 index 000000000000..502b91dc580d --- /dev/null +++ b/runtime/CMakeLists.txt @@ -0,0 +1,5 @@ +if( NOT LLVM_BUILD_RUNTIME ) + set(EXCLUDE_FROM_ALL ON) +endif() + +add_subdirectory(libprofile) diff --git a/runtime/libprofile/CMakeLists.txt b/runtime/libprofile/CMakeLists.txt new file mode 100644 index 000000000000..414ad00b4a80 --- /dev/null +++ b/runtime/libprofile/CMakeLists.txt @@ -0,0 +1,19 @@ +set(SOURCES + BasicBlockTracing.c + CommonProfiling.c + GCDAProfiling.c + PathProfiling.c + EdgeProfiling.c + OptimalEdgeProfiling.c + Profiling.h + ) + +add_llvm_library( profile_rt-static ${SOURCES} ) +set_target_properties( profile_rt-static + PROPERTIES + OUTPUT_NAME "profile_rt" ) + +add_llvm_loadable_module( profile_rt-shared ${SOURCES} ) +set_target_properties( profile_rt-shared + PROPERTIES + OUTPUT_NAME "profile_rt" ) diff --git a/runtime/libprofile/CommonProfiling.c b/runtime/libprofile/CommonProfiling.c index 1c1771c3063e..210a5e5ab78a 100644 --- a/runtime/libprofile/CommonProfiling.c +++ b/runtime/libprofile/CommonProfiling.c @@ -19,7 +19,11 @@ #include <fcntl.h> #include <stdio.h> #include <string.h> +#if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> +#else +#include <io.h> +#endif #include <stdlib.h> static char *SavedArgs = 0; diff --git a/runtime/libprofile/GCDAProfiling.c b/runtime/libprofile/GCDAProfiling.c new file mode 100644 index 000000000000..2dcf22d96472 --- /dev/null +++ b/runtime/libprofile/GCDAProfiling.c @@ -0,0 +1,152 @@ +/*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +|*===----------------------------------------------------------------------===*| +|* +|* This file implements the call back routines for the gcov profiling +|* instrumentation pass. Link against this library when running code through +|* the -insert-gcov-profiling LLVM pass. +|* +|* We emit files in a corrupt version of GCOV's "gcda" file format. These files +|* are only close enough that LCOV will happily parse them. Anything that lcov +|* ignores is missing. +|* +|* TODO: gcov is multi-process safe by having each exit open the existing file +|* and append to it. We'd like to achieve that and be thread-safe too. +|* +\*===----------------------------------------------------------------------===*/ + +#include "llvm/Support/DataTypes.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* #define DEBUG_GCDAPROFILING */ + +/* + * --- GCOV file format I/O primitives --- + */ + +static FILE *output_file = NULL; + +static void write_int32(uint32_t i) { + fwrite(&i, 4, 1, output_file); +} + +static void write_int64(uint64_t i) { + uint32_t lo, hi; + lo = i >> 0; + hi = i >> 32; + + write_int32(lo); + write_int32(hi); +} + +static char *mangle_filename(const char *orig_filename) { + /* TODO: handle GCOV_PREFIX_STRIP */ + const char *prefix; + char *filename = 0; + + prefix = getenv("GCOV_PREFIX"); + + if (!prefix) + return strdup(filename); + + filename = malloc(strlen(prefix) + 1 + strlen(orig_filename) + 1); + strcpy(filename, prefix); + strcat(filename, "/"); + strcat(filename, orig_filename); + + return filename; +} + +/* + * --- LLVM line counter API --- + */ + +/* A file in this case is a translation unit. Each .o file built with line + * profiling enabled will emit to a different file. Only one file may be + * started at a time. + */ +void llvm_gcda_start_file(const char *orig_filename) { + char *filename; + filename = mangle_filename(orig_filename); + output_file = fopen(filename, "wb"); + + /* gcda file, version 404*, stamp LLVM. */ + fwrite("adcg*404MVLL", 12, 1, output_file); + +#ifdef DEBUG_GCDAPROFILING + printf("llvmgcda: [%s]\n", orig_filename); +#endif + + free(filename); +} + +/* Given an array of pointers to counters (counters), increment the n-th one, + * where we're also given a pointer to n (predecessor). + */ +void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, + uint64_t **counters) { + uint64_t *counter; + uint32_t pred; + + pred = *predecessor; + if (pred == 0xffffffff) + return; + counter = counters[pred]; + + /* Don't crash if the pred# is out of sync. This can happen due to threads, + or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */ + if (counter) + ++*counter; +#ifdef DEBUG_GCDAPROFILING + else + printf("llvmgcda: increment_indirect_counter counters=%x, pred=%u\n", + state_table_row, *predecessor); +#endif +} + +void llvm_gcda_emit_function(uint32_t ident) { +#ifdef DEBUG_GCDAPROFILING + printf("llvmgcda: function id=%x\n", ident); +#endif + + /* function tag */ + fwrite("\0\0\0\1", 4, 1, output_file); + write_int32(2); + write_int32(ident); + write_int32(0); +} + +void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) { + uint32_t i; + /* counter #1 (arcs) tag */ + fwrite("\0\0\xa1\1", 4, 1, output_file); + write_int32(num_counters * 2); + for (i = 0; i < num_counters; ++i) { + write_int64(counters[i]); + } + +#ifdef DEBUG_GCDAPROFILING + printf("llvmgcda: %u arcs\n", num_counters); + for (i = 0; i < num_counters; ++i) { + printf("llvmgcda: %llu\n", (unsigned long long)counters[i]); + } +#endif +} + +void llvm_gcda_end_file() { + /* Write out EOF record. */ + fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file); + fclose(output_file); + output_file = NULL; + +#ifdef DEBUG_GCDAPROFILING + printf("llvmgcda: -----\n"); +#endif +} diff --git a/runtime/libprofile/Makefile b/runtime/libprofile/Makefile index 4125af60d21a..eced5e5f8ab1 100644 --- a/runtime/libprofile/Makefile +++ b/runtime/libprofile/Makefile @@ -13,9 +13,9 @@ include $(LEVEL)/Makefile.config ifneq ($(strip $(LLVMCC)),) BYTECODE_LIBRARY = 1 endif -SHARED_LIBRARY = 1 -LOADABLE_MODULE = 1 LIBRARYNAME = profile_rt +LINK_LIBS_IN_SHARED = 1 +SHARED_LIBRARY = 1 EXTRA_DIST = libprofile.exports EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/libprofile.exports diff --git a/runtime/libprofile/OptimalEdgeProfiling.c b/runtime/libprofile/OptimalEdgeProfiling.c index eb7887b2aea9..947da532605d 100644 --- a/runtime/libprofile/OptimalEdgeProfiling.c +++ b/runtime/libprofile/OptimalEdgeProfiling.c @@ -26,7 +26,7 @@ static void OptEdgeProfAtExitHandler() { /* Note that, although the array has a counter for each edge, not all * counters are updated, the ones that are not used are initialised with -1. * When loading this information the counters with value -1 have to be - * recalculated, it is guranteed that this is possible. + * recalculated, it is guaranteed that this is possible. */ write_profiling_data(OptEdgeInfo, ArrayStart, NumElements); } diff --git a/runtime/libprofile/PathProfiling.c b/runtime/libprofile/PathProfiling.c index 651e63cbdd21..283678521381 100644 --- a/runtime/libprofile/PathProfiling.c +++ b/runtime/libprofile/PathProfiling.c @@ -15,14 +15,22 @@ #include "Profiling.h" #include "llvm/Analysis/ProfileInfoTypes.h" +#include "llvm/Support/DataTypes.h" #include <sys/types.h> +#if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> +#else +#include <io.h> +#endif #include <string.h> #include <stdlib.h> -#include <unistd.h> -#include <stdint.h> #include <stdio.h> +/* Must use __inline in Microsoft C */ +#if defined(_MSC_VER) +#define inline __inline +#endif + /* note that this is used for functions with large path counts, but it is unlikely those paths will ALL be executed */ #define ARBITRARY_HASH_BIN_COUNT 100 @@ -104,8 +112,8 @@ void writeArrayTable(uint32_t fNumber, ftEntry_t* ft, uint32_t* funcCount) { } } -inline uint32_t hash (uint32_t key) { - /* this may benifit from a proper hash function */ +static inline uint32_t hash (uint32_t key) { + /* this may benefit from a proper hash function */ return key%ARBITRARY_HASH_BIN_COUNT; } @@ -147,7 +155,8 @@ void writeHashTable(uint32_t functionNumber, pathHashTable_t* hashTable) { } /* Return a pointer to this path's specific path counter */ -inline uint32_t* getPathCounter(uint32_t functionNumber, uint32_t pathNumber) { +static inline uint32_t* getPathCounter(uint32_t functionNumber, + uint32_t pathNumber) { pathHashTable_t* hashTable; pathHashEntry_t* hashEntry; uint32_t index = hash(pathNumber); @@ -214,7 +223,7 @@ void llvm_decrement_path_count (uint32_t functionNumber, uint32_t pathNumber) { * +-----------------+-----------------+ * */ -static void pathProfAtExitHandler() { +static void pathProfAtExitHandler(void) { int outFile = getOutFile(); uint32_t i; uint32_t header[2] = { PathInfo, 0 }; diff --git a/runtime/libprofile/libprofile.exports b/runtime/libprofile/libprofile.exports index b8057c7aac96..2f25be692047 100644 --- a/runtime/libprofile/libprofile.exports +++ b/runtime/libprofile/libprofile.exports @@ -5,3 +5,8 @@ llvm_start_basic_block_tracing llvm_trace_basic_block llvm_increment_path_count llvm_decrement_path_count +llvm_gcda_start_file +llvm_gcda_increment_indirect_counter +llvm_gcda_emit_function +llvm_gcda_emit_arcs +llvm_gcda_end_file |