diff options
| -rw-r--r-- | compiler-rt/lib/profile/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/profile/InstrProfiling.c | 70 | ||||
| -rw-r--r-- | compiler-rt/lib/profile/InstrProfiling.h | 52 | ||||
| -rw-r--r-- | compiler-rt/lib/profile/InstrProfilingExtras.c | 49 | ||||
| -rw-r--r-- | compiler-rt/lib/profile/PGOProfiling.c | 131 | 
5 files changed, 173 insertions, 132 deletions
diff --git a/compiler-rt/lib/profile/CMakeLists.txt b/compiler-rt/lib/profile/CMakeLists.txt index 14815874f19..20675372b23 100644 --- a/compiler-rt/lib/profile/CMakeLists.txt +++ b/compiler-rt/lib/profile/CMakeLists.txt @@ -1,6 +1,7 @@  set(PROFILE_SOURCES    GCDAProfiling.c -  PGOProfiling.c) +  InstrProfiling.c +  InstrProfilingExtras.c)  filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 arm) diff --git a/compiler-rt/lib/profile/InstrProfiling.c b/compiler-rt/lib/profile/InstrProfiling.c new file mode 100644 index 00000000000..4c9bb7e2b8f --- /dev/null +++ b/compiler-rt/lib/profile/InstrProfiling.c @@ -0,0 +1,70 @@ +/*===- InstrProfiling.c - Support library for PGO instrumentation ---------===*\ +|* +|*                     The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include "InstrProfiling.h" + +/* TODO: Calculate these with linker magic. */ +static __llvm_pgo_data *First = NULL; +static __llvm_pgo_data *Final = NULL; + +/*! + * \brief Register an instrumented function. + * + * Calls to this are emitted by clang with -fprofile-instr-generate.  Such + * calls are only required (and only emitted) on targets where we haven't + * implemented linker magic to find the bounds of the section. + * + * For now, that's all targets. + */ +void __llvm_pgo_register_function(void *Data_) { +  /* TODO: Only emit this function if we can't use linker magic. */ +  __llvm_pgo_data *Data = (__llvm_pgo_data*)Data_; +  if (!First || Data < First) +    First = Data; +  if (!Final || Data > Final) +    Final = Data; +} + +/*! \brief Get the first instrumentation record. */ +static __llvm_pgo_data *getFirst() { +  /* TODO: Use extern + linker magic instead of a static variable. */ +  return First; +} + +/*! \brief Get the last instrumentation record. */ +static __llvm_pgo_data *getLast() { +  /* TODO: Use extern + linker magic instead of a static variable. */ +  return Final + 1; +} + +/* TODO: void __llvm_pgo_get_size_for_buffer(void);  */ + +static void writeFunction(FILE *OutputFile, const __llvm_pgo_data *Data) { +  /* TODO: Requires libc: break requirement by writing directly to a buffer +   * instead of a FILE stream. +   */ +  uint32_t I; +  for (I = 0; I < Data->NameSize; ++I) +    fputc(Data->Name[I], OutputFile); +  fprintf(OutputFile, "\n%" PRIu64 "\n%u\n", Data->FuncHash, Data->NumCounters); +  for (I = 0; I < Data->NumCounters; ++I) +    fprintf(OutputFile, "%" PRIu64 "\n", Data->Counters[I]); +  fprintf(OutputFile, "\n"); +} + +void __llvm_pgo_write_buffer(FILE *OutputFile) { +  /* TODO: Requires libc: break requirement by taking a char* buffer instead of +   * a FILE stream. +   */ +  __llvm_pgo_data *I, *E; + +  for (I = getFirst(), E = getLast(); I != E; ++I) +    writeFunction(OutputFile, I); +} + diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h new file mode 100644 index 00000000000..8aaab016a16 --- /dev/null +++ b/compiler-rt/lib/profile/InstrProfiling.h @@ -0,0 +1,52 @@ +/*===- InstrProfiling.h- Support library for PGO instrumentation ----------===*\ +|* +|*                     The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include <stdio.h> +#include <stdlib.h> + +#define I386_FREEBSD (defined(__FreeBSD__) && defined(__i386__)) + +#if !I386_FREEBSD +#include <inttypes.h> +#endif + +#if !defined(_MSC_VER) && !I386_FREEBSD +#include <stdint.h> +#endif + +#if defined(_MSC_VER) +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +#elif I386_FREEBSD +/* System headers define 'size_t' incorrectly on x64 FreeBSD (prior to + * FreeBSD 10, r232261) when compiled in 32-bit mode. + */ +#define PRIu64 "llu" +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +#endif + +typedef struct __llvm_pgo_data { +  const uint32_t NameSize; +  const uint32_t NumCounters; +  const uint64_t FuncHash; +  const char *const Name; +  const uint64_t *const Counters; +} __llvm_pgo_data; + +/* TODO: void __llvm_pgo_get_size_for_buffer(void);  */ + +/*! + * \brief Write instrumentation data to the given buffer. + * + * This function is currently broken:  it shouldn't rely on libc, but it does. + * It should be changed to take a char* buffer, and write binary data directly + * to it. + */ +void __llvm_pgo_write_buffer(FILE *OutputFile); diff --git a/compiler-rt/lib/profile/InstrProfilingExtras.c b/compiler-rt/lib/profile/InstrProfilingExtras.c new file mode 100644 index 00000000000..03399a3477f --- /dev/null +++ b/compiler-rt/lib/profile/InstrProfilingExtras.c @@ -0,0 +1,49 @@ +/*===- InstrProfilingExtras.c - Support library for PGO instrumentation ---===*\ +|* +|*                     The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ + +#include "InstrProfiling.h" + +/*! \brief Write instrumentation data to the given file. */ +void __llvm_pgo_write_file(const char *OutputName) { +  /* TODO: Requires libc: move to separate translation unit. */ +  FILE *OutputFile; +  if (!OutputName || !OutputName[0]) +    return; +  OutputFile = fopen(OutputName, "w"); +  if (!OutputFile) return; + +  /* TODO: mmap file to buffer of size __llvm_pgo_get_size_for_buffer() and +   * pass the buffer in, instead of the file. +   */ +  __llvm_pgo_write_buffer(OutputFile); + +  fclose(OutputFile); +} + +/*! \brief Write instrumentation data to the default file. */ +void __llvm_pgo_write_default_file() { +  /* TODO: Requires libc: move to separate translation unit. */ +  const char *OutputName = getenv("LLVM_PROFILE_FILE"); +  if (OutputName == NULL || OutputName[0] == '\0') +    OutputName = "default.profdata"; +  __llvm_pgo_write_file(OutputName); +} + +/*! + * \brief Register to write instrumentation data to the default file at exit. + */ +void __llvm_pgo_register_write_atexit() { +  /* TODO: Requires libc: move to separate translation unit. */ +  static int HasBeenRegistered = 0; + +  if (!HasBeenRegistered) { +    HasBeenRegistered = 1; +    atexit(__llvm_pgo_write_default_file); +  } +} diff --git a/compiler-rt/lib/profile/PGOProfiling.c b/compiler-rt/lib/profile/PGOProfiling.c deleted file mode 100644 index e40eb87fc36..00000000000 --- a/compiler-rt/lib/profile/PGOProfiling.c +++ /dev/null @@ -1,131 +0,0 @@ -/*===- PGOProfiling.c - Support library for PGO instrumentation -----------===*\ -|* -|*                     The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. -|* -\*===----------------------------------------------------------------------===*/ - -#include <stdio.h> -#include <stdlib.h> - -#define I386_FREEBSD (defined(__FreeBSD__) && defined(__i386__)) - -#if !I386_FREEBSD -#include <inttypes.h> -#endif - -#if !defined(_MSC_VER) && !I386_FREEBSD -#include <stdint.h> -#endif - -#if defined(_MSC_VER) -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -#elif I386_FREEBSD -/* System headers define 'size_t' incorrectly on x64 FreeBSD (prior to - * FreeBSD 10, r232261) when compiled in 32-bit mode. - */ -#define PRIu64 "llu" -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -#endif - -typedef struct __llvm_pgo_data { -  const uint32_t NameSize; -  const uint32_t NumCounters; -  const uint64_t FuncHash; -  const char *const Name; -  const uint64_t *const Counters; -} __llvm_pgo_data; - -/* TODO: Calculate these with linker magic. */ -static __llvm_pgo_data *First = NULL; -static __llvm_pgo_data *Final = NULL; -/*! - * \brief Register an instrumented function. - * - * Calls to this are emitted by clang with -fprofile-instr-generate.  Such - * calls are only required (and only emitted) on targets where we haven't - * implemented linker magic to find the bounds of the section. - * - * For now, that's all targets. - */ -void __llvm_pgo_register_function(void *Data_) { -  /* TODO: Only emit this function if we can't use linker magic. */ -  __llvm_pgo_data *Data = (__llvm_pgo_data*)Data_; -  if (!First || Data < First) -    First = Data; -  if (!Final || Data > Final) -    Final = Data; -} - -/*! \brief Get the first instrumentation record. */ -static __llvm_pgo_data *getFirst() { -  /* TODO: Use extern + linker magic instead of a static variable. */ -  return First; -} - -/*! \brief Get the last instrumentation record. */ -static __llvm_pgo_data *getLast() { -  /* TODO: Use extern + linker magic instead of a static variable. */ -  return Final + 1; -} - -/* TODO: void __llvm_pgo_get_size_for_buffer(void);  */ -/* TODO: void __llvm_pgo_write_buffer(char *Buffer); */ - -static void writeFunction(FILE *OutputFile, const __llvm_pgo_data *Data) { -  /* TODO: Requires libc: break requirement by writing directly to a buffer -   * instead of a FILE stream. -   */ -  uint32_t I; -  for (I = 0; I < Data->NameSize; ++I) -    fputc(Data->Name[I], OutputFile); -  fprintf(OutputFile, "\n%" PRIu64 "\n%u\n", Data->FuncHash, Data->NumCounters); -  for (I = 0; I < Data->NumCounters; ++I) -    fprintf(OutputFile, "%" PRIu64 "\n", Data->Counters[I]); -  fprintf(OutputFile, "\n"); -} - -/*! \brief Write instrumentation data to the given file. */ -void __llvm_pgo_write_file(const char *OutputName) { -  /* TODO: Requires libc: move to separate translation unit. */ -  __llvm_pgo_data *I, *E; -  FILE *OutputFile; -  if (!OutputName || !OutputName[0]) -    return; -  OutputFile = fopen(OutputName, "w"); -  if (!OutputFile) return; - -  /* TODO: mmap file to buffer of size __llvm_pgo_get_size_for_buffer() and -   * call __llvm_pgo_write_buffer(). -   */ -  for (I = getFirst(), E = getLast(); I != E; ++I) -    writeFunction(OutputFile, I); - -  fclose(OutputFile); -} - -/*! \brief Write instrumentation data to the default file. */ -void __llvm_pgo_write_default_file() { -  /* TODO: Requires libc: move to separate translation unit. */ -  const char *OutputName = getenv("LLVM_PROFILE_FILE"); -  if (OutputName == NULL || OutputName[0] == '\0') -    OutputName = "default.profdata"; -  __llvm_pgo_write_file(OutputName); -} - -/*! - * \brief Register to write instrumentation data to the default file at exit. - */ -void __llvm_pgo_register_write_atexit() { -  /* TODO: Requires libc: move to separate translation unit. */ -  static int HasBeenRegistered = 0; - -  if (!HasBeenRegistered) { -    HasBeenRegistered = 1; -    atexit(__llvm_pgo_write_default_file); -  } -}  | 

