18c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\
28c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
38c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*                     The LLVM Compiler Infrastructure
48c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
58c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* This file is distributed under the University of Illinois Open Source
68c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* License. See LICENSE.TXT for details.
78c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
88c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*===----------------------------------------------------------------------===*|
98c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
108c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* This file implements the call back routines for the gcov profiling
118c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* instrumentation pass. Link against this library when running code through
128c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* the -insert-gcov-profiling LLVM pass.
138c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
148c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* We emit files in a corrupt version of GCOV's "gcda" file format. These files
158c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* are only close enough that LCOV will happily parse them. Anything that lcov
168c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* ignores is missing.
178c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
188c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* TODO: gcov is multi-process safe by having each exit open the existing file
198c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|* and append to it. We'd like to achieve that and be thread-safe too.
208c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar|*
218c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar\*===----------------------------------------------------------------------===*/
228c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
23254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth#include <errno.h>
24d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling#include <fcntl.h>
258c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <stdio.h>
268c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <stdlib.h>
278c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <string.h>
288c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <sys/stat.h>
29d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling#include <sys/mman.h>
308c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <sys/types.h>
318c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef _WIN32
328c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <direct.h>
338c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
348c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
358c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifndef _MSC_VER
368c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#include <stdint.h>
378c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#else
388c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbartypedef unsigned int uint32_t;
398c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbartypedef unsigned int uint64_t;
408c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
418c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
428c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/* #define DEBUG_GCDAPROFILING */
438c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
448c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/*
458c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar * --- GCOV file format I/O primitives ---
468c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar */
478c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
48a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling/*
49254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth * The current file name we're outputting. Used primarily for error logging.
50254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth */
51254abfa43326c2d49143529c26a86a27356e1243Chandler Carruthstatic char *filename = NULL;
52254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth
53254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth/*
54a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling * The current file we're outputting.
55a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling */
568c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarstatic FILE *output_file = NULL;
578c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
58a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling/*
592a46a60510948b5005d62025fbba307a0323ed8dBill Wendling * Buffer that we write things into.
602a46a60510948b5005d62025fbba307a0323ed8dBill Wendling */
612811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling#define WRITE_BUFFER_SIZE (128 * 1024)
622811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendlingstatic char *write_buffer = NULL;
63d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic uint64_t cur_buffer_size = 0;
64d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic uint64_t cur_pos = 0;
65d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic uint64_t file_size = 0;
662a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic int new_file = 0;
67d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic int fd = -1;
682a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
692a46a60510948b5005d62025fbba307a0323ed8dBill Wendling/*
70c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling * A list of functions to write out the data.
71c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling */
72c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendlingtypedef void (*writeout_fn)();
73c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
74c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendlingstruct writeout_fn_node {
75c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  writeout_fn fn;
76c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  struct writeout_fn_node *next;
77c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling};
78c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
792a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic struct writeout_fn_node *writeout_fn_head = NULL;
802a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic struct writeout_fn_node *writeout_fn_tail = NULL;
81c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
82c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling/*
83a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling *  A list of flush functions that our __gcov_flush() function should call.
84a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling */
85a539183bf29a42ae584244106e48c99c6630e8cdBill Wendlingtypedef void (*flush_fn)();
86a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
87a539183bf29a42ae584244106e48c99c6630e8cdBill Wendlingstruct flush_fn_node {
88a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  flush_fn fn;
89a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  struct flush_fn_node *next;
90a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling};
91a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
922a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic struct flush_fn_node *flush_fn_head = NULL;
932a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic struct flush_fn_node *flush_fn_tail = NULL;
942a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
95d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic void resize_write_buffer(uint64_t size) {
96d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  if (!new_file) return;
97d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  size += cur_pos;
98d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  if (size <= cur_buffer_size) return;
992811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  size = (size - 1) / WRITE_BUFFER_SIZE + 1;
1002811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  size *= WRITE_BUFFER_SIZE;
1012811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  write_buffer = realloc(write_buffer, size);
102d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_buffer_size = size;
1038c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
1048c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1052a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic void write_bytes(const char *s, size_t len) {
106d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  resize_write_buffer(len);
1072811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  memcpy(&write_buffer[cur_pos], s, len);
108d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_pos += len;
1092a46a60510948b5005d62025fbba307a0323ed8dBill Wendling}
1104aa08fae9b02ba9a0701fe27f58e2645d236798bBill Wendling
1112a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic void write_32bit_value(uint32_t i) {
1122a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes((char*)&i, 4);
1132a46a60510948b5005d62025fbba307a0323ed8dBill Wendling}
1142a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
1152a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic void write_64bit_value(uint64_t i) {
1162a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes((char*)&i, 8);
1178c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
1188c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1198c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarstatic uint32_t length_of_string(const char *s) {
1208c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  return (strlen(s) / 4) + 1;
1218c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
1228c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1238c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarstatic void write_string(const char *s) {
1248c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  uint32_t len = length_of_string(s);
1252a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_32bit_value(len);
1262a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes(s, strlen(s));
1272a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes("\0\0\0\0", 4 - (strlen(s) % 4));
1288c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
1298c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1302a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic uint32_t read_32bit_value() {
1312a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  uint32_t val;
1322a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
1332a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  if (new_file)
134843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    return (uint32_t)-1;
135843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
1362811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  val = *(uint32_t*)&write_buffer[cur_pos];
137d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_pos += 4;
1382a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  return val;
139843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling}
140843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
1412a46a60510948b5005d62025fbba307a0323ed8dBill Wendlingstatic uint64_t read_64bit_value() {
1422a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  uint64_t val;
143843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
1442a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  if (new_file)
145d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling    return (uint64_t)-1;
1462a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
1472811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  val = *(uint64_t*)&write_buffer[cur_pos];
148d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_pos += 8;
1492a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  return val;
150843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling}
151843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
1528c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarstatic char *mangle_filename(const char *orig_filename) {
1538c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  char *filename = 0;
154906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  int prefix_len = 0;
155ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  int prefix_strip = 0;
156ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  int level = 0;
157ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  const char *fname = orig_filename, *ptr = NULL;
158906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  const char *prefix = getenv("GCOV_PREFIX");
1592a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  const char *prefix_strip_str = getenv("GCOV_PREFIX_STRIP");
1608c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
161ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  if (!prefix)
1628c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar    return strdup(orig_filename);
1638c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1642a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  if (prefix_strip_str) {
1652a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    prefix_strip = atoi(prefix_strip_str);
166ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling
167ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling    /* Negative GCOV_PREFIX_STRIP values are ignored */
168ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling    if (prefix_strip < 0)
169ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling      prefix_strip = 0;
170ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  }
171ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling
172906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  prefix_len = strlen(prefix);
173906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  filename = malloc(prefix_len + 1 + strlen(orig_filename) + 1);
1748c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  strcpy(filename, prefix);
175ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling
176906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  if (prefix[prefix_len - 1] != '/')
177906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling    strcat(filename, "/");
178ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling
179ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  for (ptr = fname + 1; *ptr != '\0' && level < prefix_strip; ++ptr) {
180ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling    if (*ptr != '/') continue;
181ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling    fname = ptr;
182ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling    ++level;
183ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  }
184ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling
185ec63f456de18b9ac75d7546f8a53beb6ce048e67Bill Wendling  strcat(filename, fname);
1868c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
1878c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  return filename;
1888c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
1898c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
190906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendlingstatic void recursive_mkdir(char *filename) {
191906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  int i;
1928c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
193906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling  for (i = 1; filename[i] != '\0'; ++i) {
1945a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling    if (filename[i] != '/') continue;
195906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling    filename[i] = '\0';
1968c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef _WIN32
197906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling    _mkdir(filename);
1988c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#else
199906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling    mkdir(filename, 0755);  /* Some of these will fail, ignore it. */
2008c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
201906d5a5d38f2984a9b78a0786016a3d67d0798e9Bill Wendling    filename[i] = '/';
2028c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  }
2038c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
2048c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
205254abfa43326c2d49143529c26a86a27356e1243Chandler Carruthstatic int map_file() {
206d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  fseek(output_file, 0L, SEEK_END);
207d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  file_size = ftell(output_file);
208d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
2092811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  write_buffer = mmap(0, file_size, PROT_READ | PROT_WRITE,
2102811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling                      MAP_FILE | MAP_SHARED, fd, 0);
211254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  if (write_buffer == (void *)-1) {
212254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    int errnum = errno;
213254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    fprintf(stderr, "profiling: %s: cannot map: %s\n", filename,
214254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth            strerror(errnum));
215254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    return -1;
216254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  }
217254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  return 0;
218d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling}
219d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
220d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendlingstatic void unmap_file() {
221254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  if (msync(write_buffer, file_size, MS_SYNC) == -1) {
222254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    int errnum = errno;
223254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    fprintf(stderr, "profiling: %s: cannot msync: %s\n", filename,
224254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth            strerror(errnum));
225254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  }
226254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth
227254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  /* We explicitly ignore errors from unmapping because at this point the data
228254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth   * is written and we don't care.
229254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth   */
230254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  (void)munmap(write_buffer, file_size);
2312811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  write_buffer = NULL;
232d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  file_size = 0;
233d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling}
234d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
2358c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/*
2368c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar * --- LLVM line counter API ---
2378c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar */
2388c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
2398c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/* A file in this case is a translation unit. Each .o file built with line
2408c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar * profiling enabled will emit to a different file. Only one file may be
2418c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar * started at a time.
2428c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar */
24342296c7b5d69e6d79390005b6e1861ca66e3a0cbNick Lewyckyvoid llvm_gcda_start_file(const char *orig_filename, const char version[4]) {
244d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  const char *mode = "r+b";
245254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth  filename = mangle_filename(orig_filename);
246843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
247843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  /* Try just opening the file. */
248d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  new_file = 0;
249d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  fd = open(filename, O_RDWR);
2505a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling
251d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  if (fd == -1) {
252843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    /* Try opening the file, creating it if necessary. */
2532a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    new_file = 1;
254d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling    mode = "w+b";
2552811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling    fd = open(filename, O_RDWR | O_CREAT, 0644);
256d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling    if (fd == -1) {
257843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling      /* Try creating the directories first then opening the file. */
258843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling      recursive_mkdir(filename);
2592811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling      fd = open(filename, O_RDWR | O_CREAT, 0644);
260254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      if (fd == -1) {
261843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling        /* Bah! It's hopeless. */
262254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth        int errnum = errno;
263254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth        fprintf(stderr, "profiling: %s: cannot open: %s\n", filename,
264254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth                strerror(errnum));
265843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling        return;
266843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling      }
2675a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling    }
2685a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling  }
2698c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
270d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  output_file = fdopen(fd, mode);
2712a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
2722a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  /* Initialize the write buffer. */
2732811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling  write_buffer = NULL;
274d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_buffer_size = 0;
275d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_pos = 0;
276d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
277d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  if (new_file) {
2782811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling    resize_write_buffer(WRITE_BUFFER_SIZE);
2792811a0ccbadb9f8c50fe0b6aa8e4e39193fef4e7Bill Wendling    memset(write_buffer, 0, WRITE_BUFFER_SIZE);
280d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  } else {
281254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    if (map_file() == -1) {
282254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      /* mmap failed, try to recover by clobbering */
283254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      new_file = 1;
284254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      write_buffer = NULL;
285254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      cur_buffer_size = 0;
286254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      resize_write_buffer(WRITE_BUFFER_SIZE);
287254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth      memset(write_buffer, 0, WRITE_BUFFER_SIZE);
288254abfa43326c2d49143529c26a86a27356e1243Chandler Carruth    }
289d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  }
2902a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
29142296c7b5d69e6d79390005b6e1861ca66e3a0cbNick Lewycky  /* gcda file, version, stamp LLVM. */
2922a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes("adcg", 4);
2932a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes(version, 4);
2942a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes("MVLL", 4);
2952a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
2968c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef DEBUG_GCDAPROFILING
297843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  fprintf(stderr, "llvmgcda: [%s]\n", orig_filename);
2988c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
2998c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
3008c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3018c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar/* Given an array of pointers to counters (counters), increment the n-th one,
3028c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar * where we're also given a pointer to n (predecessor).
3038c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar */
3048c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarvoid llvm_gcda_increment_indirect_counter(uint32_t *predecessor,
3058c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar                                          uint64_t **counters) {
3068c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  uint64_t *counter;
3078c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  uint32_t pred;
3088c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3098c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  pred = *predecessor;
3108c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  if (pred == 0xffffffff)
3118c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar    return;
3128c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  counter = counters[pred];
3138c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3148c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  /* Don't crash if the pred# is out of sync. This can happen due to threads,
3158c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar     or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */
3168c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  if (counter)
3178c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar    ++*counter;
3188c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef DEBUG_GCDAPROFILING
3198c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  else
320de47cb8f12474c7c528a84de0ea73c743c33f015Bill Wendling    fprintf(stderr,
321843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling            "llvmgcda: increment_indirect_counter counters=%08llx, pred=%u\n",
322843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling            *counter, *predecessor);
3238c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
3248c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
3258c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
32607020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewyckyvoid llvm_gcda_emit_function(uint32_t ident, const char *function_name,
32707020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewycky                             uint8_t use_extra_checksum) {
32807020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewycky  uint32_t len = 2;
3292a46a60510948b5005d62025fbba307a0323ed8dBill Wendling
33007020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewycky  if (use_extra_checksum)
33107020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewycky    len++;
3328c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef DEBUG_GCDAPROFILING
33358c400c58019070045e548bb5173b22af092f314Nick Lewycky  fprintf(stderr, "llvmgcda: function id=0x%08x name=%s\n", ident,
33458c400c58019070045e548bb5173b22af092f314Nick Lewycky          function_name ? function_name : "NULL");
3358c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
3365a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling  if (!output_file) return;
3378c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
33858c400c58019070045e548bb5173b22af092f314Nick Lewycky  /* function tag */
3392a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes("\0\0\0\1", 4);
34058c400c58019070045e548bb5173b22af092f314Nick Lewycky  if (function_name)
34158c400c58019070045e548bb5173b22af092f314Nick Lewycky    len += 1 + length_of_string(function_name);
3422a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_32bit_value(len);
3432a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_32bit_value(ident);
3442a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_32bit_value(0);
34507020829d181dcd352ff6f01eab4d353c37a19b6Nick Lewycky  if (use_extra_checksum)
3462a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    write_32bit_value(0);
34758c400c58019070045e548bb5173b22af092f314Nick Lewycky  if (function_name)
34858c400c58019070045e548bb5173b22af092f314Nick Lewycky    write_string(function_name);
3498c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
3508c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3518c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarvoid llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
3528c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  uint32_t i;
353843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  uint64_t *old_ctrs = NULL;
354843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  uint32_t val = 0;
355d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  uint64_t save_cur_pos = cur_pos;
3565a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling
3575a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling  if (!output_file) return;
358843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
3592a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  val = read_32bit_value();
360843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
361843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  if (val != (uint32_t)-1) {
362843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    /* There are counters present in the file. Merge them. */
363843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    if (val != 0x01a10000) {
3644aa08fae9b02ba9a0701fe27f58e2645d236798bBill Wendling      fprintf(stderr, "profiling:invalid magic number (0x%08x)\n", val);
365843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling      return;
366843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    }
367843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
3682a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    val = read_32bit_value();
369843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    if (val == (uint32_t)-1 || val / 2 != num_counters) {
3704aa08fae9b02ba9a0701fe27f58e2645d236798bBill Wendling      fprintf(stderr, "profiling:invalid number of counters (%d)\n", val);
371843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling      return;
372843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    }
373843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
374843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    old_ctrs = malloc(sizeof(uint64_t) * num_counters);
3752a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    for (i = 0; i < num_counters; ++i)
3762a46a60510948b5005d62025fbba307a0323ed8dBill Wendling      old_ctrs[i] = read_64bit_value();
3772a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  }
378843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
379d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  cur_pos = save_cur_pos;
380d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
381843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  /* Counter #1 (arcs) tag */
3822a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_bytes("\0\0\xa1\1", 4);
3832a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  write_32bit_value(num_counters * 2);
3842a46a60510948b5005d62025fbba307a0323ed8dBill Wendling  for (i = 0; i < num_counters; ++i) {
3854aa08fae9b02ba9a0701fe27f58e2645d236798bBill Wendling    counters[i] += (old_ctrs ? old_ctrs[i] : 0);
3862a46a60510948b5005d62025fbba307a0323ed8dBill Wendling    write_64bit_value(counters[i]);
3874aa08fae9b02ba9a0701fe27f58e2645d236798bBill Wendling  }
388843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling
389843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  free(old_ctrs);
3908c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3918c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef DEBUG_GCDAPROFILING
392843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  fprintf(stderr, "llvmgcda:   %u arcs\n", num_counters);
3935a240c5c1746d07351fc38deb81c1794e8668d15Bill Wendling  for (i = 0; i < num_counters; ++i)
394843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling    fprintf(stderr, "llvmgcda:   %llu\n", (unsigned long long)counters[i]);
3958c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
3968c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
3978c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
3988c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbarvoid llvm_gcda_end_file() {
3998c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar  /* Write out EOF record. */
400cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth  if (output_file) {
401cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    write_bytes("\0\0\0\0\0\0\0\0", 8);
402cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth
403cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    if (new_file) {
404cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth      fwrite(write_buffer, cur_pos, 1, output_file);
405cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth      free(write_buffer);
406cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    } else {
407cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth      unmap_file();
408cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    }
409d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling
410cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    fclose(output_file);
411cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    output_file = NULL;
412cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth    write_buffer = NULL;
413d06f2fc03087e7cccda19bd550bf6fb3bc2f5ae7Bill Wendling  }
414cf5fb62c0206c6544c464fa1b414bbfa26cb3244Chandler Carruth  free(filename);
4158c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar
4168c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#ifdef DEBUG_GCDAPROFILING
417843f359862fb8370eacf8aed4e749c46a92b2e38Bill Wendling  fprintf(stderr, "llvmgcda: -----\n");
4188c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar#endif
4198c88119d6334a470e3ad638c5a1f1b42c4258ac9Daniel Dunbar}
420a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
421c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendlingvoid llvm_register_writeout_function(writeout_fn fn) {
422c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  struct writeout_fn_node *new_node = malloc(sizeof(struct writeout_fn_node));
423c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  new_node->fn = fn;
424c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  new_node->next = NULL;
425c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
426c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  if (!writeout_fn_head) {
427c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    writeout_fn_head = writeout_fn_tail = new_node;
428c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  } else {
429c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    writeout_fn_tail->next = new_node;
430c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    writeout_fn_tail = new_node;
431c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  }
432c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling}
433c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
43484b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendlingvoid llvm_writeout_files() {
435c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  struct writeout_fn_node *curr = writeout_fn_head;
436c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
437c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  while (curr) {
438c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    curr->fn();
439c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    curr = curr->next;
440c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  }
441c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling}
442c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
443c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendlingvoid llvm_delete_writeout_function_list() {
444c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  while (writeout_fn_head) {
445c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    struct writeout_fn_node *node = writeout_fn_head;
446c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    writeout_fn_head = writeout_fn_head->next;
447c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling    free(node);
448c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  }
449c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
450c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling  writeout_fn_head = writeout_fn_tail = NULL;
451c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling}
452c533304a95fbed444ea02f5f9e7c6e37debd1c43Bill Wendling
453a539183bf29a42ae584244106e48c99c6630e8cdBill Wendlingvoid llvm_register_flush_function(flush_fn fn) {
454a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  struct flush_fn_node *new_node = malloc(sizeof(struct flush_fn_node));
455a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  new_node->fn = fn;
456a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  new_node->next = NULL;
457a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
458a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  if (!flush_fn_head) {
459a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    flush_fn_head = flush_fn_tail = new_node;
460a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  } else {
461a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    flush_fn_tail->next = new_node;
462a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    flush_fn_tail = new_node;
463a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  }
464a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling}
465a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
466a539183bf29a42ae584244106e48c99c6630e8cdBill Wendlingvoid __gcov_flush() {
467a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  struct flush_fn_node *curr = flush_fn_head;
468a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
469a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  while (curr) {
470a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    curr->fn();
471a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    curr = curr->next;
472a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  }
473a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling}
474a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
475a539183bf29a42ae584244106e48c99c6630e8cdBill Wendlingvoid llvm_delete_flush_function_list() {
476a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  while (flush_fn_head) {
477a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    struct flush_fn_node *node = flush_fn_head;
478a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    flush_fn_head = flush_fn_head->next;
479a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling    free(node);
480a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  }
481a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling
482a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling  flush_fn_head = flush_fn_tail = NULL;
483a539183bf29a42ae584244106e48c99c6630e8cdBill Wendling}
48484b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling
48584b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendlingvoid llvm_gcov_init(writeout_fn wfn, flush_fn ffn) {
48684b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling  static int atexit_ran = 0;
48784b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling
48884b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling  if (wfn)
48984b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    llvm_register_writeout_function(wfn);
49084b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling
49184b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling  if (ffn)
49284b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    llvm_register_flush_function(ffn);
49384b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling
49484b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling  if (atexit_ran == 0) {
49584b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    atexit_ran = 1;
49684b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling
49784b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    /* Make sure we write out the data and delete the data structures. */
49884b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    atexit(llvm_delete_flush_function_list);
49984b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    atexit(llvm_delete_writeout_function_list);
50084b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling    atexit(llvm_writeout_files);
50184b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling  }
50284b46d300c7a4f1c3ea4e452791de7733ce0d143Bill Wendling}
503