LLVM: lib/CodeGen/XRayInstrumentation.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

33

34using namespace llvm;

35

36namespace {

37

38struct InstrumentationOptions {

39

40 bool HandleTailcall;

41

42

43

44 bool HandleAllReturns;

45};

46

48 static char ID;

49

52 }

53

59 }

60

62

63private:

64

65

66

67

68

69

72 InstrumentationOptions);

73

74

75

76

77

78

79

80

81

84 InstrumentationOptions);

85};

86

87}

88

89void XRayInstrumentation::replaceRetWithPatchableRet(

91 InstrumentationOptions op) {

92

93

95 for (auto &MBB : MF) {

97 unsigned Opc = 0;

98 if (T.isReturn() &&

99 (op.HandleAllReturns || T.getOpcode() == TII->getReturnOpcode())) {

100

101

102 Opc = TargetOpcode::PATCHABLE_RET;

103 }

105

106

107 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;

108 }

109 if (Opc != 0) {

110 auto MIB = BuildMI(MBB, T, T.getDebugLoc(), TII->get(Opc))

112 for (auto &MO : T.operands())

113 MIB.add(MO);

115 if (T.shouldUpdateAdditionalCallInfo())

116 MF.eraseAdditionalCallInfo(&T);

117 }

118 }

119 }

120

121 for (auto &I : Terminators)

122 I->eraseFromParent();

123}

124

125void XRayInstrumentation::prependRetWithPatchableExit(

127 InstrumentationOptions op) {

128 for (auto &MBB : MF)

130 unsigned Opc = 0;

131 if (T.isReturn() &&

132 (op.HandleAllReturns || T.getOpcode() == TII->getReturnOpcode())) {

133 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;

134 }

136 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;

137 }

138 if (Opc != 0) {

139

140

142 }

143 }

144}

145

146bool XRayInstrumentation::runOnMachineFunction(MachineFunction &MF) {

148 auto InstrAttr = F.getFnAttribute("function-instrument");

149 bool AlwaysInstrument = InstrAttr.isStringAttribute() &&

150 InstrAttr.getValueAsString() == "xray-always";

151 bool NeverInstrument = InstrAttr.isStringAttribute() &&

152 InstrAttr.getValueAsString() == "xray-never";

153 if (NeverInstrument && !AlwaysInstrument)

154 return false;

155 auto IgnoreLoopsAttr = F.getFnAttribute("xray-ignore-loops");

156

158 if (!AlwaysInstrument) {

159 bool IgnoreLoops = IgnoreLoopsAttr.isValid();

160 XRayThreshold = F.getFnAttributeAsParsedInteger(

161 "xray-instruction-threshold", std::numeric_limits<uint64_t>::max());

162 if (XRayThreshold == std::numeric_limits<uint64_t>::max())

163 return false;

164

165

167 for (const auto &MBB : MF)

169

170 bool TooFewInstrs = MICount < XRayThreshold;

171

172 if (!IgnoreLoops) {

173

174 auto *MDTWrapper =

175 getAnalysisIfAvailable();

176 auto *MDT = MDTWrapper ? &MDTWrapper->getDomTree() : nullptr;

178 if (!MDT) {

180 MDT = &ComputedMDT;

181 }

182

183

184 auto *MLIWrapper = getAnalysisIfAvailable();

185 auto *MLI = MLIWrapper ? &MLIWrapper->getLI() : nullptr;

187 if (!MLI) {

188 ComputedMLI.analyze(*MDT);

189 MLI = &ComputedMLI;

190 }

191

192

193

194

195 if (MLI->empty() && TooFewInstrs)

196 return false;

197 } else if (TooFewInstrs) {

198

199 return false;

200 }

201 }

202

203

204

207 if (MBI == MF.end())

208 return false;

209

210 auto *TII = MF.getSubtarget().getInstrInfo();

211 auto &FirstMBB = *MBI;

212 auto &FirstMI = *FirstMBB.begin();

213

214 if (!MF.getSubtarget().isXRaySupported()) {

215

218 Fn, "An attempt to perform XRay instrumentation for an"

219 " unsupported target."));

220

221 return false;

222 }

223

224 if (F.hasFnAttribute("xray-skip-entry")) {

225

226

227 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),

228 TII->get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));

229 }

230

231 if (F.hasFnAttribute("xray-skip-exit")) {

232 switch (MF.getTarget().getTargetTriple().getArch()) {

233 case Triple::ArchType::arm:

234 case Triple::ArchType::thumb:

235 case Triple::ArchType::aarch64:

236 case Triple::ArchType::hexagon:

237 case Triple::ArchType::loongarch64:

238 case Triple::ArchType::mips:

239 case Triple::ArchType::mipsel:

240 case Triple::ArchType::mips64:

241 case Triple::ArchType::mips64el:

242 case Triple::ArchType::riscv32:

243 case Triple::ArchType::riscv64: {

244

245 InstrumentationOptions op;

246

247 op.HandleTailcall = MF.getTarget().getTargetTriple().isRISCV();

248 op.HandleAllReturns = true;

249 prependRetWithPatchableExit(MF, TII, op);

250 break;

251 }

252 case Triple::ArchType::ppc64le:

253 case Triple::ArchType::systemz: {

254

255 InstrumentationOptions op;

256 op.HandleTailcall = false;

257 op.HandleAllReturns = true;

258 replaceRetWithPatchableRet(MF, TII, op);

259 break;

260 }

261 default: {

262

263

264 InstrumentationOptions op;

265 op.HandleTailcall = true;

266 op.HandleAllReturns = false;

267 replaceRetWithPatchableRet(MF, TII, op);

268 break;

269 }

270 }

271 }

272 return true;

273}

274

275char XRayInstrumentation::ID = 0;

278 "Insert XRay ops", false, false)

This file contains the simple types necessary to represent the attributes associated with functions a...

const HexagonInstrInfo * TII

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

This file defines the SmallVector class.

Represent the analysis usage information of a pass.

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

void setPreservesCFG()

This function should be called by the pass, iff they do not:

Diagnostic information for unsupported feature in backend.

void recalculate(ParentType &Func)

recalculate - compute a dominator tree for the given function

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

Module * getParent()

Get the module that this global value is contained inside of...

bool isTailCall(const MachineInstr &MI) const override

void diagnose(const DiagnosticInfo &DI)

Report a message to the currently installed diagnostic handler.

void analyze(const DominatorTreeBase< BlockT, false > &DomTree)

Create the loop forest using a stable algorithm.

iterator_range< iterator > terminators()

Analysis pass which computes a MachineDominatorTree.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

Function * getFunction(StringRef Name) const

Look up the specified function in the module symbol table.

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

TargetInstrInfo - Interface to description of machine instruction set.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

void initializeXRayInstrumentationPass(PassRegistry &)

char & XRayInstrumentationID

This pass inserts the XRay instrumentation sleds if they are supported by the target platform.

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.