Skip to content

Commit dd191d3

Browse files
authored
[ctxprof][nfc] Share the definition of FunctionData between compiler-rt and llvm (llvm#132136)
Mechanism to keep the compiler-rt and llvm view of `FunctionData` in sync. Since CtxInstrContextNode.h is exactly the same on both sides (there's an existing test, `compiler-rt/test/ctx_profile/TestCases/check-same-ctx-node.test`, checking that), we capture the structure in a macro that is then generated as `struct` fields on the compiler-rt side, and as `Type` objects on the llvm side. The macro needs to be told how to render a few kinds of fields. If we add more fields to FunctionData that can be described by the current known types of fields, then the llvm side would automatically be updated. If we need to add more kinds of fields, which we do by adding parameters to the macro, the llvm side (if not updated) would trigger a compilation error.
1 parent c73ad7b commit dd191d3

File tree

4 files changed

+56
-14
lines changed

4 files changed

+56
-14
lines changed

compiler-rt/lib/ctx_profile/CtxInstrContextNode.h

+18
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,24 @@ class ContextNode final {
113113
uint64_t entrycount() const { return counters()[0]; }
114114
};
115115

116+
/// The internal structure of FunctionData. This makes sure that changes to
117+
/// the fields of FunctionData either get automatically captured on the llvm
118+
/// side, or force a manual corresponding update.
119+
///
120+
/// The macro arguments (see CtxInstrProfiling.h for example):
121+
///
122+
/// PTRDECL is a macro taking 2 parameters: a type and the name of the field.
123+
/// The field is a pointer of that type;
124+
///
125+
/// VOLATILE_PTRDECL is the same as above, but for volatile pointers;
126+
///
127+
/// MUTEXDECL takes one parameter, the name of a field that is a mutex.
128+
#define CTXPROF_FUNCTION_DATA(PTRDECL, VOLATILE_PTRDECL, MUTEXDECL) \
129+
PTRDECL(FunctionData, Next) \
130+
VOLATILE_PTRDECL(ContextRoot, CtxRoot) \
131+
VOLATILE_PTRDECL(ContextNode, FlatCtx) \
132+
MUTEXDECL(Mutex)
133+
116134
/// Abstraction for the parameter passed to `__llvm_ctx_profile_fetch`.
117135
/// `startContextSection` is called before any context roots are sent for
118136
/// writing. Then one or more `writeContextual` calls are made; finally,

compiler-rt/lib/ctx_profile/CtxInstrProfiling.h

+9-7
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,19 @@ struct ContextRoot {
142142
// The current design trades off a bit of overhead at the first time a function
143143
// is encountered *for flat profiling* for avoiding size penalties.
144144
struct FunctionData {
145+
#define _PTRDECL(T, N) T *N = nullptr;
146+
#define _VOLATILE_PTRDECL(T, N) T *volatile N = nullptr;
147+
#define _MUTEXDECL(N) ::__sanitizer::SpinMutex N;
148+
CTXPROF_FUNCTION_DATA(_PTRDECL, _VOLATILE_PTRDECL, _MUTEXDECL)
149+
#undef _PTRDECL
150+
#undef _VOLATILE_PTRDECL
151+
#undef _MUTEXDECL
152+
145153
// Constructor for test only - since this is expected to be
146154
// initialized by the compiler.
147-
FunctionData() { Mutex.Init(); }
148-
149-
FunctionData *Next = nullptr;
150-
ContextRoot *volatile CtxRoot = nullptr;
151-
ContextNode *volatile FlatCtx = nullptr;
152-
155+
FunctionData() = default;
153156
ContextRoot *getOrAllocateContextRoot();
154157

155-
::__sanitizer::StaticSpinMutex Mutex;
156158
// If (unlikely) StaticSpinMutex internals change, we need to modify the LLVM
157159
// instrumentation lowering side because it is responsible for allocating and
158160
// zero-initializing ContextRoots.

llvm/include/llvm/ProfileData/CtxInstrContextNode.h

+18
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,24 @@ class ContextNode final {
113113
uint64_t entrycount() const { return counters()[0]; }
114114
};
115115

116+
/// The internal structure of FunctionData. This makes sure that changes to
117+
/// the fields of FunctionData either get automatically captured on the llvm
118+
/// side, or force a manual corresponding update.
119+
///
120+
/// The macro arguments (see CtxInstrProfiling.h for example):
121+
///
122+
/// PTRDECL is a macro taking 2 parameters: a type and the name of the field.
123+
/// The field is a pointer of that type;
124+
///
125+
/// VOLATILE_PTRDECL is the same as above, but for volatile pointers;
126+
///
127+
/// MUTEXDECL takes one parameter, the name of a field that is a mutex.
128+
#define CTXPROF_FUNCTION_DATA(PTRDECL, VOLATILE_PTRDECL, MUTEXDECL) \
129+
PTRDECL(FunctionData, Next) \
130+
VOLATILE_PTRDECL(ContextRoot, CtxRoot) \
131+
VOLATILE_PTRDECL(ContextNode, FlatCtx) \
132+
MUTEXDECL(Mutex)
133+
116134
/// Abstraction for the parameter passed to `__llvm_ctx_profile_fetch`.
117135
/// `startContextSection` is called before any context roots are sent for
118136
/// writing. Then one or more `writeContextual` calls are made; finally,

llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/IR/IntrinsicInst.h"
1919
#include "llvm/IR/Module.h"
2020
#include "llvm/IR/PassManager.h"
21+
#include "llvm/ProfileData/CtxInstrContextNode.h"
2122
#include "llvm/ProfileData/InstrProf.h"
2223
#include "llvm/Support/CommandLine.h"
2324
#include <utility>
@@ -113,13 +114,16 @@ CtxInstrumentationLowerer::CtxInstrumentationLowerer(Module &M,
113114
auto *I32Ty = Type::getInt32Ty(M.getContext());
114115
auto *I64Ty = Type::getInt64Ty(M.getContext());
115116

116-
FunctionDataTy =
117-
StructType::get(M.getContext(), {
118-
PointerTy, /*Next*/
119-
PointerTy, /*CtxRoot*/
120-
PointerTy, /*FlatCtx*/
121-
SanitizerMutexType, /*Mutex*/
122-
});
117+
#define _PTRDECL(_, __) PointerTy,
118+
#define _VOLATILE_PTRDECL(_, __) PointerTy,
119+
#define _MUTEXDECL(_) SanitizerMutexType,
120+
121+
FunctionDataTy = StructType::get(
122+
M.getContext(),
123+
{CTXPROF_FUNCTION_DATA(_PTRDECL, _VOLATILE_PTRDECL, _MUTEXDECL)});
124+
#undef _PTRDECL
125+
#undef _VOLATILE_PTRDECL
126+
#undef _MUTEXDECL
123127

124128
// The Context header.
125129
ContextNodeTy = StructType::get(M.getContext(), {

0 commit comments

Comments
 (0)