[PATCH] D23988: [compiler-rt][XRay] Support tail call sleds

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 29 03:41:42 PDT 2016

dberris created this revision.
dberris added reviewers: echristo, kcc, rSerge, majnemer.
dberris added a subscriber: llvm-commits.
dberris added a dependency: D23986: [XRay] Detect and emit sleds for sibling/tail calls.
Herald added subscribers: dberris, mehdi_amini.

This change depends on D23986 which adds tail call-specific sleds. For
now we treat them first as normal exits, and in the future leave room
for implementing this as a different kind of log entry.

The reason for deferring the change is so that we can keep the naive
logging implementation more accurate without additional complexity for
reading the log. The accuracy is gained in effectively interpreting call
stacks like:


Which when tail-call merged will end up not having any exit entries for
A() nor B(), but effectively in turn can be reasoned about as:


Although we lose the fact that A() had called B() then had called C()
with the naive approach, a later iteration that adds the explicit tail
call entries would be a change in the log format and thus necessitate a
version change for the header. We can do this later to have a chance at
releasing some tools (in D21987) that are able to handle the naive log
format, then support higher version numbers of the log format too.



Index: lib/xray/xray_interface.cc
--- lib/xray/xray_interface.cc
+++ lib/xray/xray_interface.cc
@@ -259,6 +259,37 @@
         // FIXME: Write out the nops still?
+    if (Sled.Kind == XRayEntryType::TAIL) {
+      // FIXME: Implement this in a more extensible manner, per-platform.
+      // Here we do the dance of replacing the tail call sled with a similar
+      // sequence as the entry sled, but jump to the exit sled instead, so we
+      // can treat tail call exits as if they were normal exits. In the future
+      // we'd need to distinguish between non-tail exits and tail exits for
+      // better information preservation.
+      int64_t TrampolineOffset = reinterpret_cast<int64_t>(__xray_FunctionExit) - (static_cast<int64_t>(Sled.Address) + 11);
+      if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {
+        Report("XRay Exit trampoline (%p) too far from sled (%p); distance = "
+               "%ld\n",
+               __xray_FunctionExit, reinterpret_cast<void *>(Sled.Address),
+               TrampolineOffset);
+        continue;
+      }
+      if (Enable) {
+        *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;
+        *reinterpret_cast<uint8_t *>(Sled.Address + 6) = CallOpCode;
+        *reinterpret_cast<uint32_t *>(Sled.Address + 7) = TrampolineOffset;
+        std::atomic_store_explicit(
+            reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address), MovR10Seq,
+            std::memory_order_release);
+      } else {
+        std::atomic_store_explicit(
+            reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address), Jmp9Seq,
+            std::memory_order_release);
+        // FIXME: Write out the nops still?
+      }
+    }
   XRayPatching.store(false, std::memory_order_release);
   PatchingSuccess = true;
Index: include/xray/xray_interface.h
--- include/xray/xray_interface.h
+++ include/xray/xray_interface.h
@@ -18,7 +18,7 @@
 extern "C" {
-enum XRayEntryType { ENTRY = 0, EXIT = 1 };
+enum XRayEntryType { ENTRY = 0, EXIT = 1, TAIL = 2 };
 // Provide a function to invoke for when instrumentation points are hit. This is
 // a user-visible control surface that overrides the default implementation. The

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23988.69552.patch
Type: text/x-patch
Size: 2365 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160829/95ee0d4a/attachment.bin>

More information about the llvm-commits mailing list