1/*===- InstrProfilingPlatformOther.c - Profile data default platform ------===*\
2|*
3|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4|* See https://llvm.org/LICENSE.txt for license information.
5|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6|*
7\*===----------------------------------------------------------------------===*/
8
9// This file defines a fallback implementation to compute the locations of
10// profile data sections, for targets that don't have linker support. No
11// commonly used targets use this codepath.
12//
13// This implementation expects the compiler instrumentation pass to define a
14// constructor in each file which calls into this file.
15
16#if (!defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
17 !defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
18 !defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && \
19 !defined(__wasm__) && !defined(__HAIKU__) && \
20 !defined(COMPILER_RT_PROFILE_BAREMETAL)) || \
21 defined(__NVPTX__)
22
23#include "InstrProfiling.h"
24#include "InstrProfilingInternal.h"
25
26#if defined(__NVPTX__)
27extern __llvm_profile_gpu_sections INSTR_PROF_SECT_BOUNDS_TABLE;
28#define DataFirst INSTR_PROF_SECT_BOUNDS_TABLE.DataStart
29#define DataLast INSTR_PROF_SECT_BOUNDS_TABLE.DataStop
30#define NamesFirst INSTR_PROF_SECT_BOUNDS_TABLE.NamesStart
31#define NamesLast INSTR_PROF_SECT_BOUNDS_TABLE.NamesStop
32#define CountersFirst INSTR_PROF_SECT_BOUNDS_TABLE.CountersStart
33#define CountersLast INSTR_PROF_SECT_BOUNDS_TABLE.CountersStop
34#else
35static const __llvm_profile_data *DataFirst = NULL;
36static const __llvm_profile_data *DataLast = NULL;
37static const char *NamesFirst = NULL;
38static const char *NamesLast = NULL;
39static char *CountersFirst = NULL;
40static char *CountersLast = NULL;
41#endif
42static const VTableProfData *VTableProfDataFirst = NULL;
43static const VTableProfData *VTableProfDataLast = NULL;
44static const char *VNamesFirst = NULL;
45static const char *VNamesLast = NULL;
46static char *BitmapFirst = NULL;
47static char *BitmapLast = NULL;
48
49static const void *getMinAddr(const void *A1, const void *A2) {
50 return A1 < A2 ? A1 : A2;
51}
52
53static const void *getMaxAddr(const void *A1, const void *A2) {
54 return A1 > A2 ? A1 : A2;
55}
56
57/*!
58 * \brief Register an instrumented function.
59 *
60 * Calls to this are emitted by clang with -fprofile-instr-generate. Such
61 * calls are only required (and only emitted) on targets where we haven't
62 * implemented linker magic to find the bounds of the sections.
63 */
64COMPILER_RT_VISIBILITY
65void __llvm_profile_register_function(void *Data_) {
66 /* TODO: Only emit this function if we can't use linker magic. */
67 const __llvm_profile_data *Data = (__llvm_profile_data *)Data_;
68
69#if defined(__NVPTX__)
70 // NVPTX stores absolute counter addresses to avoid circular dependencies in
71 // PTX global variable initializers. Convert to a relative offset so the
72 // host-side profile reader sees the standard format.
73 {
74 uintptr_t Rel = (uintptr_t)Data->CounterPtr - (uintptr_t)Data_;
75 __builtin_memcpy((char *)Data_ +
76 __builtin_offsetof(__llvm_profile_data, CounterPtr),
77 &Rel, sizeof(Rel));
78 }
79#endif
80
81 if (!DataFirst) {
82 DataFirst = Data;
83 DataLast = Data + 1;
84 CountersFirst = (char *)((uintptr_t)Data_ + Data->CounterPtr);
85 CountersLast =
86 CountersFirst + Data->NumCounters * __llvm_profile_counter_entry_size();
87 return;
88 }
89
90 DataFirst = (const __llvm_profile_data *)getMinAddr(DataFirst, Data);
91 CountersFirst = (char *)getMinAddr(
92 CountersFirst, (char *)((uintptr_t)Data_ + Data->CounterPtr));
93
94 DataLast = (const __llvm_profile_data *)getMaxAddr(DataLast, Data + 1);
95 CountersLast = (char *)getMaxAddr(
96 CountersLast,
97 (char *)((uintptr_t)Data_ + Data->CounterPtr) +
98 Data->NumCounters * __llvm_profile_counter_entry_size());
99}
100
101COMPILER_RT_VISIBILITY
102void __llvm_profile_register_names_function(void *NamesStart,
103 uint64_t NamesSize) {
104 if (!NamesFirst) {
105 NamesFirst = (const char *)NamesStart;
106 NamesLast = (const char *)NamesStart + NamesSize;
107 return;
108 }
109 NamesFirst = (const char *)getMinAddr(NamesFirst, NamesStart);
110 NamesLast =
111 (const char *)getMaxAddr(NamesLast, (const char *)NamesStart + NamesSize);
112}
113
114COMPILER_RT_VISIBILITY
115const __llvm_profile_data *__llvm_profile_begin_data(void) { return DataFirst; }
116COMPILER_RT_VISIBILITY
117const __llvm_profile_data *__llvm_profile_end_data(void) { return DataLast; }
118COMPILER_RT_VISIBILITY const VTableProfData *
119__llvm_profile_begin_vtables(void) {
120 return VTableProfDataFirst;
121}
122COMPILER_RT_VISIBILITY const VTableProfData *__llvm_profile_end_vtables(void) {
123 return VTableProfDataLast;
124}
125COMPILER_RT_VISIBILITY
126const char *__llvm_profile_begin_names(void) { return NamesFirst; }
127COMPILER_RT_VISIBILITY
128const char *__llvm_profile_end_names(void) { return NamesLast; }
129COMPILER_RT_VISIBILITY
130const char *__llvm_profile_begin_vtabnames(void) { return VNamesFirst; }
131COMPILER_RT_VISIBILITY
132const char *__llvm_profile_end_vtabnames(void) { return VNamesLast; }
133COMPILER_RT_VISIBILITY
134char *__llvm_profile_begin_counters(void) { return CountersFirst; }
135COMPILER_RT_VISIBILITY
136char *__llvm_profile_end_counters(void) { return CountersLast; }
137COMPILER_RT_VISIBILITY
138char *__llvm_profile_begin_bitmap(void) { return BitmapFirst; }
139COMPILER_RT_VISIBILITY
140char *__llvm_profile_end_bitmap(void) { return BitmapLast; }
141
142COMPILER_RT_VISIBILITY
143ValueProfNode *__llvm_profile_begin_vnodes(void) {
144 return 0;
145}
146COMPILER_RT_VISIBILITY
147ValueProfNode *__llvm_profile_end_vnodes(void) { return 0; }
148
149COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = 0;
150COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = 0;
151
152COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
153 return 0;
154}
155
156#endif
157