1212#include " llvm/Analysis/CtxProfAnalysis.h"
1313#include " llvm/Analysis/OptimizationRemarkEmitter.h"
1414#include " llvm/IR/Analysis.h"
15+ #include " llvm/IR/Constants.h"
1516#include " llvm/IR/DiagnosticInfo.h"
1617#include " llvm/IR/GlobalValue.h"
1718#include " llvm/IR/IRBuilder.h"
19+ #include " llvm/IR/InstrTypes.h"
1820#include " llvm/IR/Instructions.h"
1921#include " llvm/IR/IntrinsicInst.h"
2022#include " llvm/IR/Module.h"
@@ -55,14 +57,15 @@ class CtxInstrumentationLowerer final {
5557 Module &M;
5658 ModuleAnalysisManager &MAM;
5759 Type *ContextNodeTy = nullptr ;
58- Type *FunctionDataTy = nullptr ;
60+ StructType *FunctionDataTy = nullptr ;
5961
6062 DenseSet<const Function *> ContextRootSet;
6163 Function *StartCtx = nullptr ;
6264 Function *GetCtx = nullptr ;
6365 Function *ReleaseCtx = nullptr ;
6466 GlobalVariable *ExpectedCalleeTLS = nullptr ;
6567 GlobalVariable *CallsiteInfoTLS = nullptr ;
68+ Constant *CannotBeRootInitializer = nullptr ;
6669
6770public:
6871 CtxInstrumentationLowerer (Module &M, ModuleAnalysisManager &MAM);
@@ -117,12 +120,29 @@ CtxInstrumentationLowerer::CtxInstrumentationLowerer(Module &M,
117120
118121#define _PTRDECL (_, __ ) PointerTy,
119122#define _VOLATILE_PTRDECL (_, __ ) PointerTy,
123+ #define _CONTEXT_ROOT PointerTy,
120124#define _MUTEXDECL (_ ) SanitizerMutexType,
121125
122126 FunctionDataTy = StructType::get (
123- M.getContext (),
124- { CTXPROF_FUNCTION_DATA (_PTRDECL, _VOLATILE_PTRDECL, _MUTEXDECL)});
127+ M.getContext (), { CTXPROF_FUNCTION_DATA (_PTRDECL, _CONTEXT_ROOT,
128+ _VOLATILE_PTRDECL, _MUTEXDECL)});
125129#undef _PTRDECL
130+ #undef _CONTEXT_ROOT
131+ #undef _VOLATILE_PTRDECL
132+ #undef _MUTEXDECL
133+
134+ #define _PTRDECL (_, __ ) Constant::getNullValue(PointerTy),
135+ #define _VOLATILE_PTRDECL (_, __ ) _PTRDECL(_, __)
136+ #define _MUTEXDECL (_ ) Constant::getNullValue(SanitizerMutexType),
137+ #define _CONTEXT_ROOT \
138+ Constant::getIntegerValue ( \
139+ PointerTy, \
140+ APInt (M.getDataLayout ().getPointerTypeSizeInBits (PointerTy), 1U )),
141+ CannotBeRootInitializer = ConstantStruct::get (
142+ FunctionDataTy, {CTXPROF_FUNCTION_DATA (_PTRDECL, _CONTEXT_ROOT,
143+ _VOLATILE_PTRDECL, _MUTEXDECL)});
144+ #undef _PTRDECL
145+ #undef _CONTEXT_ROOT
126146#undef _VOLATILE_PTRDECL
127147#undef _MUTEXDECL
128148
@@ -134,8 +154,8 @@ CtxInstrumentationLowerer::CtxInstrumentationLowerer(Module &M,
134154 I32Ty, /* NumCallsites*/
135155 });
136156
137- // Define a global for each entrypoint. We'll reuse the entrypoint's name as
138- // prefix. We assume the entrypoint names to be unique.
157+ // Define a global for each entrypoint. We'll reuse the entrypoint's name
158+ // as prefix. We assume the entrypoint names to be unique.
139159 for (const auto &Fname : ContextRoots) {
140160 if (const auto *F = M.getFunction (Fname)) {
141161 if (F->isDeclaration ())
@@ -145,10 +165,10 @@ CtxInstrumentationLowerer::CtxInstrumentationLowerer(Module &M,
145165 for (const auto &I : BB)
146166 if (const auto *CB = dyn_cast<CallBase>(&I))
147167 if (CB->isMustTailCall ()) {
148- M.getContext ().emitError (
149- " The function " + Fname +
150- " was indicated as a context root, but it features musttail "
151- " calls, which is not supported." );
168+ M.getContext ().emitError (" The function " + Fname +
169+ " was indicated as a context root, "
170+ " but it features musttail "
171+ " calls, which is not supported." );
152172 }
153173 }
154174 }
@@ -240,6 +260,14 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
240260 return false ;
241261 }();
242262
263+ if (HasMusttail && ContextRootSet.contains (&F)) {
264+ F.getContext ().emitError (
265+ " [ctx_prof] A function with musttail calls was explicitly requested as "
266+ " root. That is not supported because we cannot instrument a return "
267+ " instruction to release the context: " +
268+ F.getName ());
269+ return false ;
270+ }
243271 auto &Head = F.getEntryBlock ();
244272 for (auto &I : Head) {
245273 // Find the increment intrinsic in the entry basic block.
@@ -263,9 +291,14 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
263291 // regular function)
264292 // Don't set a name, they end up taking a lot of space and we don't need
265293 // them.
294+
295+ // Zero-initialize the FunctionData, except for functions that have
296+ // musttail calls. There, we set the CtxRoot field to 1, which will be
297+ // treated as a "can't be set as root".
266298 TheRootFuctionData = new GlobalVariable (
267299 M, FunctionDataTy, false , GlobalVariable::InternalLinkage,
268- Constant::getNullValue (FunctionDataTy));
300+ HasMusttail ? CannotBeRootInitializer
301+ : Constant::getNullValue (FunctionDataTy));
269302
270303 if (ContextRootSet.contains (&F)) {
271304 Context = Builder.CreateCall (
@@ -366,10 +399,6 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
366399 }
367400 }
368401 }
369- // FIXME: This would happen if the entrypoint tailcalls. A way to fix would be
370- // to disallow this, (so this then stays as an error), another is to detect
371- // that and then do a wrapper or disallow the tail call. This only affects
372- // instrumentation, when we want to detect the call graph.
373402 if (!HasMusttail && !ContextWasReleased)
374403 F.getContext ().emitError (
375404 " [ctx_prof] A function that doesn't have musttail calls was "
0 commit comments