summaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/AArch64AsmPrinter.cpp
diff options
context:
space:
mode:
authorDean Michael Berris <dberris@google.com>2016-11-17 05:15:37 +0000
committerDean Michael Berris <dberris@google.com>2016-11-17 05:15:37 +0000
commita685ab458dd2158a14142c9a6c68656bff704951 (patch)
treeca6096af123698ef4b0850d0d4f503483c6fcb58 /lib/Target/AArch64/AArch64AsmPrinter.cpp
parentfb21e4d6fc9ff15b231354be4068c3f732deee02 (diff)
[XRay] Support AArch64 in LLVM
This patch adds XRay support in LLVM for AArch64 targets. This patch is one of a series: Clang: https://reviews.llvm.org/D26415 compiler-rt: https://reviews.llvm.org/D26413 Author: rSerge Reviewers: rengolin, dberris Subscribers: amehsan, aemerson, llvm-commits, iid_iunknown Differential Revision: https://reviews.llvm.org/D26412 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287209 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/AArch64/AArch64AsmPrinter.cpp')
-rw-r--r--lib/Target/AArch64/AArch64AsmPrinter.cpp124
1 files changed, 123 insertions, 1 deletions
diff --git a/lib/Target/AArch64/AArch64AsmPrinter.cpp b/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 3c57576c40c..f0564ef0b89 100644
--- a/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -37,6 +37,8 @@
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
@@ -68,6 +70,14 @@ public:
const MachineInstr &MI);
void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
const MachineInstr &MI);
+
+ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
+ void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
+ void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
+
+ void EmitXRayTable();
+ void EmitSled(const MachineInstr &MI, SledKind Kind);
+
/// \brief tblgen'erated driver function for lowering simple MI->MC
/// pseudo instructions.
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
@@ -83,7 +93,9 @@ public:
bool runOnMachineFunction(MachineFunction &F) override {
AArch64FI = F.getInfo<AArch64FunctionInfo>();
STI = static_cast<const AArch64Subtarget*>(&F.getSubtarget());
- return AsmPrinter::runOnMachineFunction(F);
+ bool Result = AsmPrinter::runOnMachineFunction(F);
+ EmitXRayTable();
+ return Result;
}
private:
@@ -122,6 +134,104 @@ private:
//===----------------------------------------------------------------------===//
+void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
+{
+ EmitSled(MI, SledKind::FUNCTION_ENTER);
+}
+
+void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
+{
+ EmitSled(MI, SledKind::FUNCTION_EXIT);
+}
+
+void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
+{
+ EmitSled(MI, SledKind::TAIL_CALL);
+}
+
+void AArch64AsmPrinter::EmitXRayTable()
+{
+ //TODO: merge the logic for ELF XRay sleds at a higher level, so to avoid
+ // code duplication as it is now for x86_64, ARM32 and AArch64.
+ if (Sleds.empty())
+ return;
+ if (STI->isTargetELF()) {
+ auto PrevSection = OutStreamer->getCurrentSectionOnly();
+ auto Fn = MF->getFunction();
+ MCSection *Section;
+ if (Fn->hasComdat())
+ Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
+ Fn->getComdat()->getName());
+ else
+ Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
+ ELF::SHF_ALLOC);
+
+ // Before we switch over, we force a reference to a label inside the
+ // xray_instr_map section. Since EmitXRayTable() is always called just
+ // before the function's end, we assume that this is happening after the
+ // last return instruction.
+ //
+ // We then align the reference to 16 byte boundaries, which we determined
+ // experimentally to be beneficial to avoid causing decoder stalls.
+ MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
+ OutStreamer->EmitCodeAlignment(16);
+ OutStreamer->EmitSymbolValue(Tmp, 8, false);
+ OutStreamer->SwitchSection(Section);
+ OutStreamer->EmitLabel(Tmp);
+ for (const auto &Sled : Sleds) {
+ OutStreamer->EmitSymbolValue(Sled.Sled, 8);
+ OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
+ auto Kind = static_cast<uint8_t>(Sled.Kind);
+ OutStreamer->EmitBytes(
+ StringRef(reinterpret_cast<const char *>(&Kind), 1));
+ OutStreamer->EmitBytes(
+ StringRef(reinterpret_cast<const char *>(&Sled.AlwaysInstrument), 1));
+ OutStreamer->EmitZeros(14);
+ }
+ OutStreamer->SwitchSection(PrevSection);
+ }
+ Sleds.clear();
+}
+
+void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
+{
+ static const int8_t NoopsInSledCount = 7;
+ // We want to emit the following pattern:
+ //
+ // .Lxray_sled_N:
+ // ALIGN
+ // B #32
+ // ; 7 NOP instructions (28 bytes)
+ // .tmpN
+ //
+ // We need the 28 bytes (7 instructions) because at runtime, we'd be patching
+ // over the full 32 bytes (8 instructions) with the following pattern:
+ //
+ // STP X0, X30, [SP, #-16]! ; push X0 and the link register to the stack
+ // LDR W0, #12 ; W0 := function ID
+ // LDR X16,#12 ; X16 := addr of __xray_FunctionEntry or __xray_FunctionExit
+ // BLR X16 ; call the tracing trampoline
+ // ;DATA: 32 bits of function ID
+ // ;DATA: lower 32 bits of the address of the trampoline
+ // ;DATA: higher 32 bits of the address of the trampoline
+ // LDP X0, X30, [SP], #16 ; pop X0 and the link register from the stack
+ //
+ OutStreamer->EmitCodeAlignment(4);
+ auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
+ OutStreamer->EmitLabel(CurSled);
+ auto Target = OutContext.createTempSymbol();
+
+ // Emit "B #32" instruction, which jumps over the next 28 bytes.
+ EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(32));
+
+ for (int8_t I = 0; I < NoopsInSledCount; I++)
+ EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
+
+ OutStreamer->EmitLabel(Target);
+ recordSled(CurSled, MI, Kind);
+}
+
void AArch64AsmPrinter::EmitEndOfAsmFile(Module &M) {
const Triple &TT = TM.getTargetTriple();
if (TT.isOSBinFormatMachO()) {
@@ -567,6 +677,18 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) {
case TargetOpcode::PATCHPOINT:
return LowerPATCHPOINT(*OutStreamer, SM, *MI);
+
+ case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
+ LowerPATCHABLE_FUNCTION_ENTER(*MI);
+ return;
+
+ case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
+ LowerPATCHABLE_FUNCTION_EXIT(*MI);
+ return;
+
+ case TargetOpcode::PATCHABLE_TAIL_CALL:
+ LowerPATCHABLE_TAIL_CALL(*MI);
+ return;
}
// Finally, do the automated lowerings for everything else.