aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/CMakeLists.txt5
-rw-r--r--runtime/libprofile/CMakeLists.txt19
-rw-r--r--runtime/libprofile/CommonProfiling.c4
-rw-r--r--runtime/libprofile/GCDAProfiling.c152
-rw-r--r--runtime/libprofile/Makefile4
-rw-r--r--runtime/libprofile/OptimalEdgeProfiling.c2
-rw-r--r--runtime/libprofile/PathProfiling.c21
-rw-r--r--runtime/libprofile/libprofile.exports5
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