llvm.org GIT mirror llvm / 87ff4c1
[XRay] Merge instrumentation point table emission code into AsmPrinter. Summary: No need to have this per-architecture. While there, unify 32-bit ARM's behaviour with what changed elsewhere and start function names lowercase as per the coding standards. Individual entry emission code goes to the entry's own class. Fully tested on amd64, cross-builds on both ARMs and PowerPC. Reviewers: dberris Subscribers: aemerson, llvm-commits Differential Revision: https://reviews.llvm.org/D28209 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290858 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 3 years ago
8 changed file(s) with 64 addition(s) and 150 deletion(s). Raw diff Collapse all Expand all
207207 SledKind Kind;
208208 bool AlwaysInstrument;
209209 const class Function *Fn;
210
211 void emit(int, MCStreamer *, const MCSymbol *) const;
210212 };
211213
212214 // All the sleds to be emitted.
214216
215217 // Helper function to record a given XRay sled.
216218 void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind);
219
220 /// Emit a table with all XRay instrumentation points.
221 void emitXRayTable();
217222
218223 //===------------------------------------------------------------------===//
219224 // MachineFunctionPass Implementation.
3636 #include "llvm/MC/MCExpr.h"
3737 #include "llvm/MC/MCInst.h"
3838 #include "llvm/MC/MCSection.h"
39 #include "llvm/MC/MCSectionELF.h"
40 #include "llvm/MC/MCSectionMachO.h"
3941 #include "llvm/MC/MCStreamer.h"
4042 #include "llvm/MC/MCSymbolELF.h"
4143 #include "llvm/MC/MCValue.h"
26092611
26102612 void AsmPrinterHandler::markFunctionEnd() {}
26112613
2614 // In the binary's "xray_instr_map" section, an array of these function entries
2615 // describes each instrumentation point. When XRay patches your code, the index
2616 // into this table will be given to your handler as a patch point identifier.
2617 void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out,
2618 const MCSymbol *CurrentFnSym) const {
2619 Out->EmitSymbolValue(Sled, Bytes);
2620 Out->EmitSymbolValue(CurrentFnSym, Bytes);
2621 auto Kind8 = static_cast(Kind);
2622 Out->EmitBytes(StringRef(reinterpret_cast(&Kind8), 1));
2623 Out->EmitBytes(
2624 StringRef(reinterpret_cast(&AlwaysInstrument), 1));
2625 Out->EmitZeros(2 * Bytes - 2); // Pad the previous two entries
2626 }
2627
2628 void AsmPrinter::emitXRayTable() {
2629 if (Sleds.empty())
2630 return;
2631
2632 auto PrevSection = OutStreamer->getCurrentSectionOnly();
2633 auto Fn = MF->getFunction();
2634 MCSection *Section = nullptr;
2635 if (MF->getSubtarget().getTargetTriple().isOSBinFormatELF()) {
2636 if (Fn->hasComdat()) {
2637 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
2638 ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
2639 Fn->getComdat()->getName());
2640 } else {
2641 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
2642 ELF::SHF_ALLOC);
2643 }
2644 } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) {
2645 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
2646 SectionKind::getReadOnlyWithRel());
2647 } else {
2648 llvm_unreachable("Unsupported target");
2649 }
2650
2651 // Before we switch over, we force a reference to a label inside the
2652 // xray_instr_map section. Since this function is always called just
2653 // before the function's end, we assume that this is happening after
2654 // the last return instruction.
2655
2656 auto WordSizeBytes = TM.getPointerSize();
2657 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
2658 OutStreamer->EmitCodeAlignment(16);
2659 OutStreamer->EmitSymbolValue(Tmp, WordSizeBytes, false);
2660 OutStreamer->SwitchSection(Section);
2661 OutStreamer->EmitLabel(Tmp);
2662 for (const auto &Sled : Sleds)
2663 Sled.emit(WordSizeBytes, OutStreamer.get(), CurrentFnSym);
2664
2665 OutStreamer->SwitchSection(PrevSection);
2666 Sleds.clear();
2667 }
2668
26122669 void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI,
26132670 SledKind Kind) {
26142671 auto Fn = MI.getParent()->getParent()->getFunction();
7575 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
7676 void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
7777
78 void EmitXRayTable();
7978 void EmitSled(const MachineInstr &MI, SledKind Kind);
8079
8180 /// \brief tblgen'erated driver function for lowering simple MI->MC
9493 AArch64FI = F.getInfo();
9594 STI = static_cast(&F.getSubtarget());
9695 bool Result = AsmPrinter::runOnMachineFunction(F);
97 EmitXRayTable();
96 emitXRayTable();
9897 return Result;
9998 }
10099
147146 void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
148147 {
149148 EmitSled(MI, SledKind::TAIL_CALL);
150 }
151
152 void AArch64AsmPrinter::EmitXRayTable()
153 {
154 //TODO: merge the logic for ELF XRay sleds at a higher level, so to avoid
155 // code duplication as it is now for x86_64, ARM32 and AArch64.
156 if (Sleds.empty())
157 return;
158
159 auto PrevSection = OutStreamer->getCurrentSectionOnly();
160 auto Fn = MF->getFunction();
161 MCSection *Section;
162
163 if (STI->isTargetELF()) {
164 if (Fn->hasComdat())
165 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
166 ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
167 Fn->getComdat()->getName());
168 else
169 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
170 ELF::SHF_ALLOC);
171 } else if (STI->isTargetMachO()) {
172 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
173 SectionKind::getReadOnlyWithRel());
174 } else {
175 llvm_unreachable("Unsupported target");
176 }
177
178 // Before we switch over, we force a reference to a label inside the
179 // xray_instr_map section. Since EmitXRayTable() is always called just
180 // before the function's end, we assume that this is happening after the
181 // last return instruction.
182 //
183 // We then align the reference to 16 byte boundaries, which we determined
184 // experimentally to be beneficial to avoid causing decoder stalls.
185 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
186 OutStreamer->EmitCodeAlignment(16);
187 OutStreamer->EmitSymbolValue(Tmp, 8, false);
188 OutStreamer->SwitchSection(Section);
189 OutStreamer->EmitLabel(Tmp);
190 for (const auto &Sled : Sleds) {
191 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
192 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
193 auto Kind = static_cast(Sled.Kind);
194 OutStreamer->EmitBytes(
195 StringRef(reinterpret_cast(&Kind), 1));
196 OutStreamer->EmitBytes(
197 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
198 OutStreamer->EmitZeros(14);
199 }
200 OutStreamer->SwitchSection(PrevSection);
201
202 Sleds.clear();
203149 }
204150
205151 void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
162162
163163 // Emit the rest of the function body.
164164 EmitFunctionBody();
165
166 // Emit the XRay table for this function.
167 EmitXRayTable();
168165
169166 // If we need V4T thumb mode Register Indirect Jump pads, emit them.
170167 // These are created per function, rather than per TU, since it's
112112 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
113113 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
114114 void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
115 // Helper function that emits the XRay sleds we've collected for a particular
116 // function.
117 void EmitXRayTable();
118115
119116 private:
120117 void EmitSled(const MachineInstr &MI, SledKind Kind);
2121 #include "llvm/MC/MCExpr.h"
2222 #include "llvm/MC/MCInst.h"
2323 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCSymbolELF.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCSectionMachO.h"
2724 #include "llvm/MC/MCInstBuilder.h"
2825 #include "llvm/MC/MCStreamer.h"
2926 using namespace llvm;
225222 {
226223 EmitSled(MI, SledKind::TAIL_CALL);
227224 }
228
229 void ARMAsmPrinter::EmitXRayTable()
230 {
231 if (Sleds.empty())
232 return;
233
234 MCSection *Section = nullptr;
235 if (Subtarget->isTargetELF()) {
236 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
237 ELF::SHF_ALLOC | ELF::SHF_GROUP |
238 ELF::SHF_MERGE,
239 0, CurrentFnSym->getName());
240 } else if (Subtarget->isTargetMachO()) {
241 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
242 SectionKind::getReadOnlyWithRel());
243 } else {
244 llvm_unreachable("Unsupported target");
245 }
246
247 auto PrevSection = OutStreamer->getCurrentSectionOnly();
248 OutStreamer->SwitchSection(Section);
249 for (const auto &Sled : Sleds) {
250 OutStreamer->EmitSymbolValue(Sled.Sled, 4);
251 OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
252 auto Kind = static_cast(Sled.Kind);
253 OutStreamer->EmitBytes(
254 StringRef(reinterpret_cast(&Kind), 1));
255 OutStreamer->EmitBytes(
256 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
257 OutStreamer->EmitZeros(6);
258 }
259 OutStreamer->SwitchSection(PrevSection);
260
261 Sleds.clear();
262 }
6969 EmitFunctionBody();
7070
7171 // Emit the XRay table for this function.
72 EmitXRayTable();
72 emitXRayTable();
7373
7474 // We didn't modify anything.
7575 return false;
11121112 if (auto MaybeOperand = MCIL.LowerMachineOperand(&MI, MO))
11131113 TC.addOperand(MaybeOperand.getValue());
11141114 OutStreamer->EmitInstruction(TC, getSubtargetInfo());
1115 }
1116
1117 void X86AsmPrinter::EmitXRayTable() {
1118 if (Sleds.empty())
1119 return;
1120
1121 auto PrevSection = OutStreamer->getCurrentSectionOnly();
1122 auto Fn = MF->getFunction();
1123 MCSection *Section = nullptr;
1124 if (Subtarget->isTargetELF()) {
1125 if (Fn->hasComdat()) {
1126 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
1127 ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
1128 Fn->getComdat()->getName());
1129 } else {
1130 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
1131 ELF::SHF_ALLOC);
1132 }
1133 } else if (Subtarget->isTargetMachO()) {
1134 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
1135 SectionKind::getReadOnlyWithRel());
1136 } else {
1137 llvm_unreachable("Unsupported target");
1138 }
1139
1140 // Before we switch over, we force a reference to a label inside the
1141 // xray_instr_map section. Since EmitXRayTable() is always called just
1142 // before the function's end, we assume that this is happening after the
1143 // last return instruction.
1144 //
1145 // We then align the reference to 16 byte boundaries, which we determined
1146 // experimentally to be beneficial to avoid causing decoder stalls.
1147 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
1148 OutStreamer->EmitCodeAlignment(16);
1149 OutStreamer->EmitSymbolValue(Tmp, 8, false);
1150 OutStreamer->SwitchSection(Section);
1151 OutStreamer->EmitLabel(Tmp);
1152 for (const auto &Sled : Sleds) {
1153 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
1154 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
1155 auto Kind = static_cast(Sled.Kind);
1156 OutStreamer->EmitBytes(
1157 StringRef(reinterpret_cast(&Kind), 1));
1158 OutStreamer->EmitBytes(
1159 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
1160 OutStreamer->EmitZeros(14);
1161 }
1162 OutStreamer->SwitchSection(PrevSection);
1163
1164 Sleds.clear();
11651115 }
11661116
11671117 // Returns instruction preceding MBBI in MachineFunction.