[XRay][CodeGen] Use PIC-friendly code in XRay sleds and remove synthetic references in .text

Summary:
This is a re-roll of D36615 which uses PLT relocations in the back-end
to the call to __xray_CustomEvent() when building in -fPIC and
-fxray-instrument mode.

Reviewers: pcc, djasper, bkramer

Subscribers: sdardis, javed.absar, llvm-commits

Differential Revision: https://reviews.llvm.org/D37373

llvm-svn: 312466
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index fd2837b..36d8112 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -1047,20 +1047,20 @@
   // We want to emit the following pattern, which follows the x86 calling
   // convention to prepare for the trampoline call to be patched in.
   //
-  //   <args placement according SysV64 calling convention>
   //   .p2align 1, ...
   // .Lxray_event_sled_N:
-  //   jmp +N                    // jump across the call instruction
-  //   callq __xray_CustomEvent  // force relocation to symbol
-  //   <args cleanup, jump to here>
-  //
-  // The relative jump needs to jump forward 24 bytes:
-  // 10 (args) + 5 (nops) + 9 (cleanup)
+  //   jmp +N                        // jump across the instrumentation sled
+  //   ...                           // set up arguments in register
+  //   callq __xray_CustomEvent@plt  // force dependency to symbol
+  //   ...
+  //   <jump here>
   //
   // After patching, it would look something like:
   //
   //   nopw (2-byte nop)
+  //   ...
   //   callq __xrayCustomEvent  // already lowered
+  //   ...
   //
   // ---
   // First we emit the label and the jump.
@@ -1072,49 +1072,57 @@
   // Use a two-byte `jmp`. This version of JMP takes an 8-bit relative offset as
   // an operand (computed as an offset from the jmp instruction).
   // FIXME: Find another less hacky way do force the relative jump.
-  OutStreamer->EmitBytes("\xeb\x14");
+  OutStreamer->EmitBinaryData("\xeb\x0f");
 
   // The default C calling convention will place two arguments into %rcx and
   // %rdx -- so we only work with those.
-  unsigned UsedRegs[] = {X86::RDI, X86::RSI, X86::RAX};
+  unsigned UsedRegs[] = {X86::RDI, X86::RSI};
+  bool UsedMask[] = {false, false};
 
-  // Because we will use %rax, we preserve that across the call.
-  EmitAndCountInstruction(MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
-
-  // Then we put the operands in the %rdi and %rsi registers.
+  // Then we put the operands in the %rdi and %rsi registers. We spill the
+  // values in the register before we clobber them, and mark them as used in
+  // UsedMask. In case the arguments are already in the correct register, we use
+  // emit nops appropriately sized to keep the sled the same size in every
+  // situation.
   for (unsigned I = 0; I < MI.getNumOperands(); ++I)
     if (auto Op = MCIL.LowerMachineOperand(&MI, MI.getOperand(I))) {
-      if (Op->isImm())
-        EmitAndCountInstruction(MCInstBuilder(X86::MOV64ri)
+      assert(Op->isReg() && "Only support arguments in registers");
+      if (Op->getReg() != UsedRegs[I]) {
+        UsedMask[I] = true;
+        EmitAndCountInstruction(
+            MCInstBuilder(X86::PUSH64r).addReg(UsedRegs[I]));
+        EmitAndCountInstruction(MCInstBuilder(X86::MOV64rr)
                                     .addReg(UsedRegs[I])
-                                    .addImm(Op->getImm()));
-      else if (Op->isReg()) {
-        if (Op->getReg() != UsedRegs[I])
-          EmitAndCountInstruction(MCInstBuilder(X86::MOV64rr)
-                                      .addReg(UsedRegs[I])
-                                      .addReg(Op->getReg()));
-        else
-          EmitNops(*OutStreamer, 3, Subtarget->is64Bit(), getSubtargetInfo());
+                                    .addReg(Op->getReg()));
+      } else {
+        EmitNops(*OutStreamer, 4, Subtarget->is64Bit(), getSubtargetInfo());
       }
     }
 
   // We emit a hard dependency on the __xray_CustomEvent symbol, which is the
-  // name of the trampoline to be implemented by the XRay runtime. We put this
-  // explicitly in the %rax register.
+  // name of the trampoline to be implemented by the XRay runtime.
   auto TSym = OutContext.getOrCreateSymbol("__xray_CustomEvent");
   MachineOperand TOp = MachineOperand::CreateMCSymbol(TSym);
-  EmitAndCountInstruction(MCInstBuilder(X86::MOV64ri)
-                              .addReg(X86::RAX)
-                              .addOperand(MCIL.LowerSymbolOperand(TOp, TSym)));
+  if (isPositionIndependent())
+    TOp.setTargetFlags(X86II::MO_PLT);
 
   // Emit the call instruction.
-  EmitAndCountInstruction(MCInstBuilder(X86::CALL64r).addReg(X86::RAX));
+  EmitAndCountInstruction(MCInstBuilder(X86::CALL64pcrel32)
+                              .addOperand(MCIL.LowerSymbolOperand(TOp, TSym)));
 
   // Restore caller-saved and used registers.
-  OutStreamer->AddComment("xray custom event end.");
-  EmitAndCountInstruction(MCInstBuilder(X86::POP64r).addReg(X86::RAX));
+  for (unsigned I = sizeof UsedMask; I-- > 0;)
+    if (UsedMask[I])
+      EmitAndCountInstruction(MCInstBuilder(X86::POP64r).addReg(UsedRegs[I]));
+    else
+      EmitNops(*OutStreamer, 1, Subtarget->is64Bit(), getSubtargetInfo());
 
-  recordSled(CurSled, MI, SledKind::CUSTOM_EVENT);
+  OutStreamer->AddComment("xray custom event end.");
+
+  // Record the sled version. Older versions of this sled were spelled
+  // differently, so we let the runtime handle the different offsets we're
+  // using.
+  recordSled(CurSled, MI, SledKind::CUSTOM_EVENT, 1);
 }
 
 void X86AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
@@ -1125,7 +1133,6 @@
   // .Lxray_sled_N:
   //   jmp .tmpN
   //   # 9 bytes worth of noops
-  // .tmpN
   //
   // We need the 9 bytes because at runtime, we'd be patching over the full 11
   // bytes with the following pattern:
@@ -1136,14 +1143,12 @@
   auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
   OutStreamer->EmitCodeAlignment(2);
   OutStreamer->EmitLabel(CurSled);
-  auto Target = OutContext.createTempSymbol();
 
   // Use a two-byte `jmp`. This version of JMP takes an 8-bit relative offset as
   // an operand (computed as an offset from the jmp instruction).
   // FIXME: Find another less hacky way do force the relative jump.
   OutStreamer->EmitBytes("\xeb\x09");
   EmitNops(*OutStreamer, 9, Subtarget->is64Bit(), getSubtargetInfo());
-  OutStreamer->EmitLabel(Target);
   recordSled(CurSled, MI, SledKind::FUNCTION_ENTER);
 }