37 struct InstrumentationOptions {
43 bool HandleAllReturns;
71 InstrumentationOptions);
83 InstrumentationOptions);
88 void XRayInstrumentation::replaceRetWithPatchableRet(
90 InstrumentationOptions
op) {
94 for (
auto &MBB : MF) {
95 for (
auto &
T : MBB.terminators()) {
101 Opc = TargetOpcode::PATCHABLE_RET;
106 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
109 auto MIB =
BuildMI(MBB,
T,
T.getDebugLoc(), TII->
get(Opc))
110 .addImm(
T.getOpcode());
111 for (
auto &MO :
T.operands())
118 for (
auto &
I : Terminators)
119 I->eraseFromParent();
122 void XRayInstrumentation::prependRetWithPatchableExit(
124 InstrumentationOptions op) {
126 for (
auto &
T : MBB.terminators()) {
130 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
133 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
145 auto InstrAttr =
F.getFnAttribute(
"function-instrument");
147 InstrAttr.isStringAttribute() &&
148 InstrAttr.getValueAsString() ==
"xray-always";
149 Attribute Attr =
F.getFnAttribute(
"xray-instruction-threshold");
150 unsigned XRayThreshold = 0;
151 if (!AlwaysInstrument) {
159 for (
const auto &MBB : MF)
160 MICount += MBB.size();
163 auto *MDT = getAnalysisIfAvailable<MachineDominatorTree>();
166 ComputedMDT.
getBase().recalculate(MF);
171 auto *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
174 ComputedMLI.
getBase().analyze(MDT->getBase());
181 if (MLI->empty() && MICount < XRayThreshold)
192 auto *TII = MF.getSubtarget().getInstrInfo();
193 auto &FirstMBB = *MBI;
194 auto &FirstMI = *FirstMBB.begin();
196 if (!MF.getSubtarget().isXRaySupported()) {
197 FirstMI.emitError(
"An attempt to perform XRay instrumentation for an" 198 " unsupported target.");
204 BuildMI(FirstMBB, FirstMI, FirstMI.getDebugLoc(),
205 TII->
get(TargetOpcode::PATCHABLE_FUNCTION_ENTER));
207 switch (MF.getTarget().getTargetTriple().getArch()) {
208 case Triple::ArchType::arm:
209 case Triple::ArchType::thumb:
210 case Triple::ArchType::aarch64:
211 case Triple::ArchType::mips:
212 case Triple::ArchType::mipsel:
213 case Triple::ArchType::mips64:
214 case Triple::ArchType::mips64el: {
216 InstrumentationOptions
op;
217 op.HandleTailcall =
false;
218 op.HandleAllReturns =
true;
219 prependRetWithPatchableExit(MF, TII, op);
222 case Triple::ArchType::ppc64le: {
224 InstrumentationOptions
op;
225 op.HandleTailcall =
false;
226 op.HandleAllReturns =
true;
227 replaceRetWithPatchableRet(MF, TII, op);
233 InstrumentationOptions
op;
234 op.HandleTailcall =
true;
235 op.HandleAllReturns =
false;
236 replaceRetWithPatchableRet(MF, TII, op);
246 "Insert XRay ops",
false,
false)
const MachineInstrBuilder & add(const MachineOperand &MO) const
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
void push_back(const T &Elt)
#define INITIALIZE_PASS_DEPENDENCY(depName)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
const HexagonInstrInfo * TII
This file contains the simple types necessary to represent the attributes associated with functions a...
No attributes have been set.
char & XRayInstrumentationID
This pass inserts the XRay instrumentation sleds if they are supported by the target platform...
TargetInstrInfo - Interface to description of machine instruction set.
void initializeXRayInstrumentationPass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Represent the analysis usage information of a pass.
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
virtual bool isTailCall(const MachineInstr &Inst) const
Determines whether Inst is a tail call instruction.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
unsigned getReturnOpcode() const
INITIALIZE_PASS_BEGIN(XRayInstrumentation, "xray-instrumentation", "Insert XRay ops", false, false) INITIALIZE_PASS_END(XRayInstrumentation
StringRef getValueAsString() const
Return the attribute's value as a string.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
DomTreeBase< MachineBasicBlock > & getBase()
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
LoopInfoBase< MachineBasicBlock, MachineLoop > & getBase()