]> granicus.if.org Git - llvm/commitdiff
[xray] Add XRay support for Mach-O in CodeGen
authorKuba Mracek <mracek@apple.com>
Wed, 23 Nov 2016 02:07:04 +0000 (02:07 +0000)
committerKuba Mracek <mracek@apple.com>
Wed, 23 Nov 2016 02:07:04 +0000 (02:07 +0000)
Currently, XRay only supports emitting the XRay table (xray_instr_map) on ELF binaries. Let's add Mach-O support.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287734 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64AsmPrinter.cpp
lib/Target/ARM/ARMMCInstLower.cpp
lib/Target/X86/X86MCInstLower.cpp
test/CodeGen/ARM/xray-armv6-attribute-instrumentation.ll
test/CodeGen/ARM/xray-armv7-attribute-instrumentation.ll
test/CodeGen/ARM/xray-tail-call-sled.ll
test/CodeGen/X86/xray-attribute-instrumentation.ll
test/CodeGen/X86/xray-tail-call-sled.ll

index 2d49ccc46d4232097e2355b3722538bf039e9c5e..b2d96a32fd3af441021f3aedcb1984fee8384b54 100644 (file)
@@ -39,6 +39,7 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
@@ -155,10 +156,12 @@ void AArch64AsmPrinter::EmitXRayTable()
   // code duplication as it is now for x86_64, ARM32 and AArch64.
   if (Sleds.empty())
     return;
+
+  auto PrevSection = OutStreamer->getCurrentSectionOnly();
+  auto Fn = MF->getFunction();
+  MCSection *Section;
+
   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,
@@ -166,31 +169,37 @@ void AArch64AsmPrinter::EmitXRayTable()
     else
       Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
         ELF::SHF_ALLOC);
+  } else if (STI->isTargetMachO()) {
+    Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
+                                         SectionKind::getReadOnlyWithRel());
+  } else {
+    llvm_unreachable("Unsupported target");
+  }
 
-    // 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);
+  // 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();
 }
 
index 79f61652d61c2528ea8d3a2093dec3ab010830f6..dde91a7e04ee36cedb53f2020b3d7da03f483445 100644 (file)
@@ -24,6 +24,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCStreamer.h"
 using namespace llvm;
@@ -228,24 +229,33 @@ void ARMAsmPrinter::EmitXRayTable()
 {
   if (Sleds.empty())
     return;
+
+  MCSection *Section = nullptr;
   if (Subtarget->isTargetELF()) {
-    auto *Section = OutContext.getELFSection(
-      "xray_instr_map", ELF::SHT_PROGBITS,
-      ELF::SHF_ALLOC | ELF::SHF_GROUP | ELF::SHF_MERGE, 0,
-      CurrentFnSym->getName());
-    auto PrevSection = OutStreamer->getCurrentSectionOnly();
-    OutStreamer->SwitchSection(Section);
-    for (const auto &Sled : Sleds) {
-      OutStreamer->EmitSymbolValue(Sled.Sled, 4);
-      OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
-      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(6);
-    }
-    OutStreamer->SwitchSection(PrevSection);
+    Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
+                                       ELF::SHF_ALLOC | ELF::SHF_GROUP |
+                                           ELF::SHF_MERGE,
+                                       0, CurrentFnSym->getName());
+  } else if (Subtarget->isTargetMachO()) {
+    Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
+                                         SectionKind::getReadOnlyWithRel());
+  } else {
+    llvm_unreachable("Unsupported target");
   }
+
+  auto PrevSection = OutStreamer->getCurrentSectionOnly();
+  OutStreamer->SwitchSection(Section);
+  for (const auto &Sled : Sleds) {
+    OutStreamer->EmitSymbolValue(Sled.Sled, 4);
+    OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
+    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(6);
+  }
+  OutStreamer->SwitchSection(PrevSection);
+
   Sleds.clear();
 }
index 4108462e26ca5d33ae2deb57f399deead2d03d52..1273482d3f1b4efeab094f50a8fcdf82163737b4 100644 (file)
@@ -41,6 +41,7 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
@@ -1116,10 +1117,11 @@ void X86AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLo
 void X86AsmPrinter::EmitXRayTable() {
   if (Sleds.empty())
     return;
+  
+  auto PrevSection = OutStreamer->getCurrentSectionOnly();
+  auto Fn = MF->getFunction();
+  MCSection *Section = nullptr;
   if (Subtarget->isTargetELF()) {
-    auto PrevSection = OutStreamer->getCurrentSectionOnly();
-    auto Fn = MF->getFunction();
-    MCSection *Section = nullptr;
     if (Fn->hasComdat()) {
       Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
                                          ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
@@ -1128,31 +1130,37 @@ void X86AsmPrinter::EmitXRayTable() {
       Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
                                          ELF::SHF_ALLOC);
     }
+  } else if (Subtarget->isTargetMachO()) {
+    Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
+                                         SectionKind::getReadOnlyWithRel());
+  } else {
+    llvm_unreachable("Unsupported target");
+  }
 
-    // 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);
+  // 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();
 }
 
index c89c21e44a9f73b02bdfc71adda230d8391f2ac0..8a8c667b2d8d6f9b422500782de3bd0c5d57cc48 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=asm -o - -mtriple=armv6-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=armv6-apple-ios6.0.0  < %s | FileCheck %s
 
 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK-LABEL: Lxray_sled_0:
index 842d9bc2a5605243471311165f827dab5951433e..07852cd68796210bf068057ff08044094620e3a9 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=armv7-apple-ios6.0.0  < %s | FileCheck %s
 
 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK-LABEL: Lxray_sled_0:
index d62a3b78662ac41d04b5c67f2f7f00968ba86f39..f6769c04603a58a42dcbd1d8e09fded67eeb473b 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=armv7-apple-ios6.0.0    < %s | FileCheck %s
 
 define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK:       .p2align        2
@@ -48,6 +49,6 @@ define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-alway
 ; CHECK-NEXT:  nop
 ; CHECK-LABEL: Ltmp3:
   %retval = tail call i32 @callee()
-; CHECK:       b       callee
+; CHECK:       b       {{.*}}callee
   ret i32 %retval
 }
index 7dfab650fbc115901f432e2a739a2aabe5c116d0..c52ccf9356bc52833ea1ffa1117c11052d80bfce 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=x86_64-darwin-unknown    < %s | FileCheck %s
 
 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK:       .p2align 1, 0x90
@@ -13,11 +14,11 @@ define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always"
 ; CHECK-NEXT:  nopw %cs:512(%rax,%rax)
 }
 ; CHECK:       .p2align 4, 0x90
-; CHECK-NEXT:  .quad .Lxray_synthetic_0
-; CHECK-NEXT:  .section xray_instr_map,{{.*}}
+; CHECK-NEXT:  .quad {{.*}}xray_synthetic_0
+; CHECK-NEXT:  .section {{.*}}xray_instr_map
 ; CHECK-LABEL: Lxray_synthetic_0:
-; CHECK:       .quad .Lxray_sled_0
-; CHECK:       .quad .Lxray_sled_1
+; CHECK:       .quad {{.*}}xray_sled_0
+; CHECK:       .quad {{.*}}xray_sled_1
 
 ; We test multiple returns in a single function to make sure we're getting all
 ; of them with XRay instrumentation.
@@ -44,9 +45,9 @@ NotEqual:
 ; CHECK-NEXT:  nopw %cs:512(%rax,%rax)
 }
 ; CHECK:       .p2align 4, 0x90
-; CHECK-NEXT:  .quad .Lxray_synthetic_1
-; CHECK-NEXT:  .section xray_instr_map,{{.*}}
+; CHECK-NEXT:  .quad {{.*}}xray_synthetic_1
+; CHECK-NEXT:  .section {{.*}}xray_instr_map
 ; CHECK-LABEL: Lxray_synthetic_1:
-; CHECK:       .quad .Lxray_sled_2
-; CHECK:       .quad .Lxray_sled_3
-; CHECK:       .quad .Lxray_sled_4
+; CHECK:       .quad {{.*}}xray_sled_2
+; CHECK:       .quad {{.*}}xray_sled_3
+; CHECK:       .quad {{.*}}xray_sled_4
index 451993c881536cf6d1846bb48a6a44ffd1ead0b6..ece786a5e809bd6d323e4483b03429d71db36543 100644 (file)
@@ -1,4 +1,5 @@
 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -filetype=asm -o - -mtriple=x86_64-darwin-unknown    < %s | FileCheck %s
 
 define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK:       .p2align 1, 0x90
@@ -13,11 +14,11 @@ define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-alway
 ; CHECK-NEXT:  nopw %cs:512(%rax,%rax)
 }
 ; CHECK:       .p2align 4, 0x90
-; CHECK-NEXT:  .quad .Lxray_synthetic_0
-; CHECK-NEXT:  .section xray_instr_map,{{.*}}
+; CHECK-NEXT:  .quad {{.*}}xray_synthetic_0
+; CHECK-NEXT:  .section {{.*}}xray_instr_map
 ; CHECK-LABEL: Lxray_synthetic_0:
-; CHECK:       .quad .Lxray_sled_0
-; CHECK:       .quad .Lxray_sled_1
+; CHECK:       .quad {{.*}}xray_sled_0
+; CHECK:       .quad {{.*}}xray_sled_1
 
 define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
 ; CHECK:       .p2align 1, 0x90
@@ -31,11 +32,11 @@ define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-alway
 ; CHECK-NEXT:  nopw 512(%rax,%rax)
 ; CHECK-LABEL: Ltmp2:
   %retval = tail call i32 @callee()
-; CHECK:       jmp callee  # TAILCALL
+; CHECK:       jmp {{.*}}callee {{.*}}# TAILCALL
   ret i32 %retval
 }
 ; CHECK:       .p2align 4, 0x90
-; CHECK-NEXT:  .quad .Lxray_synthetic_1
+; CHECK-NEXT:  .quad {{.*}}xray_synthetic_1
 ; CHECK-LABEL: Lxray_synthetic_1:
-; CHECK:       .quad .Lxray_sled_2
-; CHECK:       .quad .Lxray_sled_3
+; CHECK:       .quad {{.*}}xray_sled_2
+; CHECK:       .quad {{.*}}xray_sled_3