[llvm] r251573 - ARM: add support for WatchOS's compact unwind information.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 28 15:56:42 PDT 2015


Author: tnorthover
Date: Wed Oct 28 17:56:36 2015
New Revision: 251573

URL: http://llvm.org/viewvc/llvm-project?rev=251573&view=rev
Log:
ARM: add support for WatchOS's compact unwind information.

Added:
    llvm/trunk/test/CodeGen/ARM/cfi-alignment.ll
    llvm/trunk/test/MC/MachO/ARM/compact-unwind-armv7k.s
Modified:
    llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
    llvm/trunk/lib/MC/MCDwarf.cpp
    llvm/trunk/lib/MC/MCObjectFileInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.h
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
    llvm/trunk/test/CodeGen/ARM/eh-resume-darwin.ll
    llvm/trunk/test/CodeGen/ARM/v7k-abi-align.ll
    llvm/trunk/test/CodeGen/ARM/vfp-reg-stride.ll

Modified: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectFileInfo.h?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectFileInfo.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectFileInfo.h Wed Oct 28 17:56:36 2015
@@ -35,7 +35,13 @@ protected:
   /// without an associated EH frame section.
   bool SupportsCompactUnwindWithoutEHFrame;
 
-  /// Some encoding values for EH.
+  /// OmitDwarfIfHaveCompactUnwind - True if the target object file
+  /// supports having some functions with compact unwind and other with
+  /// dwarf unwind.
+  bool OmitDwarfIfHaveCompactUnwind;
+
+  /// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values
+  /// for EH.
   unsigned PersonalityEncoding;
   unsigned LSDAEncoding;
   unsigned FDECFIEncoding;
@@ -200,6 +206,10 @@ public:
   bool getSupportsCompactUnwindWithoutEHFrame() const {
     return SupportsCompactUnwindWithoutEHFrame;
   }
+  bool getOmitDwarfIfHaveCompactUnwind() const {
+    return OmitDwarfIfHaveCompactUnwind;
+  }
+
   bool getCommDirectiveSupportsAlignment() const {
     return CommDirectiveSupportsAlignment;
   }

Modified: llvm/trunk/lib/MC/MCDwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCDwarf.cpp (original)
+++ llvm/trunk/lib/MC/MCDwarf.cpp Wed Oct 28 17:56:36 2015
@@ -1536,6 +1536,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectS
 
   const MCSymbol *DummyDebugKey = nullptr;
   NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
+  bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
   for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
     const MCDwarfFrameInfo &Frame = FrameArray[i];
 
@@ -1545,7 +1546,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectS
       FDEEnd = nullptr;
     }
 
-    if (!NeedsEHFrameSection && Frame.CompactUnwindEncoding !=
+    if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
           MOFI->getCompactUnwindDwarfEHFrameOnly())
       // Don't generate an EH frame if we don't need one. I.e., it's taken care
       // of by the compact unwind encoding.

Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Wed Oct 28 17:56:36 2015
@@ -29,6 +29,10 @@ static bool useCompactUnwind(const Tripl
   if (T.getArch() == Triple::aarch64)
     return true;
 
+  // armv7k always has it.
+  if (T.isWatchOS())
+    return true;
+
   // Use it on newer version of OS X.
   if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6))
     return true;
@@ -48,6 +52,9 @@ void MCObjectFileInfo::initMachOMCObject
   if (T.isOSDarwin() && T.getArch() == Triple::aarch64)
     SupportsCompactUnwindWithoutEHFrame = true;
 
+  if (T.isWatchOS())
+    OmitDwarfIfHaveCompactUnwind = true;
+
   PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel
     | dwarf::DW_EH_PE_sdata4;
   LSDAEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel;
@@ -193,9 +200,11 @@ void MCObjectFileInfo::initMachOMCObject
                              SectionKind::getReadOnly());
 
     if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
-      CompactUnwindDwarfEHFrameOnly = 0x04000000;
+      CompactUnwindDwarfEHFrameOnly = 0x04000000;  // UNWIND_X86_64_MODE_DWARF
     else if (T.getArch() == Triple::aarch64)
-      CompactUnwindDwarfEHFrameOnly = 0x03000000;
+      CompactUnwindDwarfEHFrameOnly = 0x03000000;  // UNWIND_ARM64_MODE_DWARF
+    else if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
+      CompactUnwindDwarfEHFrameOnly = 0x04000000;  // UNWIND_ARM_MODE_DWARF
   }
 
   // Debug Information.
@@ -767,6 +776,7 @@ void MCObjectFileInfo::InitMCObjectFileI
   CommDirectiveSupportsAlignment = true;
   SupportsWeakOmittedEHFrame = true;
   SupportsCompactUnwindWithoutEHFrame = false;
+  OmitDwarfIfHaveCompactUnwind = false;
 
   PersonalityEncoding = LSDAEncoding = FDECFIEncoding = TTypeEncoding =
       dwarf::DW_EH_PE_absptr;

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Wed Oct 28 17:56:36 2015
@@ -813,9 +813,9 @@ ARMTargetLowering::ARMTargetLowering(con
   setOperationAction(ISD::STACKSAVE,          MVT::Other, Expand);
   setOperationAction(ISD::STACKRESTORE,       MVT::Other, Expand);
 
-  if (!Subtarget->isTargetMachO()) {
-    // Non-MachO platforms may return values in these registers via the
-    // personality function.
+  if (!Subtarget->useSjLjEH()) {
+    // Platforms which do not use SjLj EH may return values in these registers
+    // via the personality function.
     setExceptionPointerRegister(ARM::R0);
     setExceptionSelectorRegister(ARM::R1);
   }
@@ -889,7 +889,7 @@ ARMTargetLowering::ARMTargetLowering(con
   setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
   setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
   setOperationAction(ISD::EH_SJLJ_SETUP_DISPATCH, MVT::Other, Custom);
-  if (Subtarget->isTargetDarwin())
+  if (Subtarget->useSjLjEH())
     setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume");
 
   setOperationAction(ISD::SETCC,     MVT::i32, Expand);

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp Wed Oct 28 17:56:36 2015
@@ -151,6 +151,8 @@ void ARMSubtarget::initializeEnvironment
   UseNaClTrap = false;
   GenLongCalls = false;
   UnsafeFPMath = false;
+  UseSjLjEH = (isTargetDarwin() &&
+               TargetTriple.getSubArch() != Triple::ARMSubArch_v7k);
 }
 
 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
@@ -324,7 +326,10 @@ bool ARMSubtarget::enableAtomicExpand()
 }
 
 bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const {
-  return isSwift() && !MF.getFunction()->optForMinSize();
+  // For general targets, the prologue can grow when VFPs are allocated with
+  // stride 4 (more vpush instructions). But WatchOS uses a compact unwind
+  // format which it's more important to get right.
+  return isTargetWatchOS() || (isSwift() && !MF.getFunction()->optForMinSize());
 }
 
 bool ARMSubtarget::useMovt(const MachineFunction &MF) const {

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.h?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h Wed Oct 28 17:56:36 2015
@@ -212,6 +212,9 @@ protected:
   /// Target machine allowed unsafe FP math (such as use of NEON fp)
   bool UnsafeFPMath;
 
+  /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS).
+  bool UseSjLjEH;
+
   /// stackAlignment - The minimum alignment known to hold of the stack frame on
   /// entry to the function and which must be maintained by every function.
   unsigned stackAlignment;
@@ -345,6 +348,7 @@ public:
   bool hasMPExtension() const { return HasMPExtension; }
   bool hasDSP() const { return HasDSP; }
   bool useNaClTrap() const { return UseNaClTrap; }
+  bool useSjLjEH() const { return UseSjLjEH; }
   bool genLongCalls() const { return GenLongCalls; }
 
   bool hasFP16() const { return HasFP16; }

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp Wed Oct 28 17:56:36 2015
@@ -25,12 +25,15 @@
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCMachObjectWriter.h"
 #include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCValue.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/MachO.h"
 #include "llvm/Support/TargetParser.h"
 #include "llvm/Support/raw_ostream.h"
@@ -779,6 +782,220 @@ void ARMAsmBackend::applyFixup(const MCF
   }
 }
 
+namespace CU {
+
+/// \brief Compact unwind encoding values.
+enum CompactUnwindEncodings {
+  UNWIND_ARM_MODE_MASK                         = 0x0F000000,
+  UNWIND_ARM_MODE_FRAME                        = 0x01000000,
+  UNWIND_ARM_MODE_FRAME_D                      = 0x02000000,
+  UNWIND_ARM_MODE_DWARF                        = 0x04000000,
+
+  UNWIND_ARM_FRAME_STACK_ADJUST_MASK           = 0x00C00000,
+
+  UNWIND_ARM_FRAME_FIRST_PUSH_R4               = 0x00000001,
+  UNWIND_ARM_FRAME_FIRST_PUSH_R5               = 0x00000002,
+  UNWIND_ARM_FRAME_FIRST_PUSH_R6               = 0x00000004,
+
+  UNWIND_ARM_FRAME_SECOND_PUSH_R8              = 0x00000008,
+  UNWIND_ARM_FRAME_SECOND_PUSH_R9              = 0x00000010,
+  UNWIND_ARM_FRAME_SECOND_PUSH_R10             = 0x00000020,
+  UNWIND_ARM_FRAME_SECOND_PUSH_R11             = 0x00000040,
+  UNWIND_ARM_FRAME_SECOND_PUSH_R12             = 0x00000080,
+
+  UNWIND_ARM_FRAME_D_REG_COUNT_MASK            = 0x00000F00,
+
+  UNWIND_ARM_DWARF_SECTION_OFFSET              = 0x00FFFFFF
+};
+
+} // end CU namespace
+
+/// Generate compact unwind encoding for the function based on the CFI
+/// instructions. If the CFI instructions describe a frame that cannot be
+/// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which
+/// tells the runtime to fallback and unwind using dwarf.
+uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
+    ArrayRef<MCCFIInstruction> Instrs) const {
+  DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n");
+  // Only armv7k uses CFI based unwinding.
+  if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K)
+    return 0;
+  // No .cfi directives means no frame.
+  if (Instrs.empty())
+    return 0;
+  // Start off assuming CFA is at SP+0.
+  int CFARegister = ARM::SP;
+  int CFARegisterOffset = 0;
+  // Mark savable registers as initially unsaved
+  DenseMap<unsigned, int> RegOffsets;
+  int FloatRegCount = 0;
+  // Process each .cfi directive and build up compact unwind info.
+  for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
+    int Reg;
+    const MCCFIInstruction &Inst = Instrs[i];
+    switch (Inst.getOperation()) {
+    case MCCFIInstruction::OpDefCfa: // DW_CFA_def_cfa
+      CFARegisterOffset = -Inst.getOffset();
+      CFARegister = MRI.getLLVMRegNum(Inst.getRegister(), true);
+      break;
+    case MCCFIInstruction::OpDefCfaOffset: // DW_CFA_def_cfa_offset
+      CFARegisterOffset = -Inst.getOffset();
+      break;
+    case MCCFIInstruction::OpDefCfaRegister: // DW_CFA_def_cfa_register
+      CFARegister = MRI.getLLVMRegNum(Inst.getRegister(), true);
+      break;
+    case MCCFIInstruction::OpOffset: // DW_CFA_offset
+      Reg = MRI.getLLVMRegNum(Inst.getRegister(), true);
+      if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
+        RegOffsets[Reg] = Inst.getOffset();
+      else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
+        RegOffsets[Reg] = Inst.getOffset();
+        ++FloatRegCount;
+      } else {
+        DEBUG_WITH_TYPE("compact-unwind",
+                        llvm::dbgs() << ".cfi_offset on unknown register="
+                                     << Inst.getRegister() << "\n");
+        return CU::UNWIND_ARM_MODE_DWARF;
+      }
+      break;
+    case MCCFIInstruction::OpRelOffset: // DW_CFA_advance_loc
+      // Ignore
+      break;
+    default:
+      // Directive not convertable to compact unwind, bail out.
+      DEBUG_WITH_TYPE("compact-unwind",
+                      llvm::dbgs()
+                          << "CFI directive not compatiable with comact "
+                             "unwind encoding, opcode=" << Inst.getOperation()
+                          << "\n");
+      return CU::UNWIND_ARM_MODE_DWARF;
+      break;
+    }
+  }
+
+  // If no frame set up, return no unwind info.
+  if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
+    return 0;
+
+  // Verify standard frame (lr/r7) was used.
+  if (CFARegister != ARM::R7) {
+    DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "frame register is "
+                                                   << CFARegister
+                                                   << " instead of r7\n");
+    return CU::UNWIND_ARM_MODE_DWARF;
+  }
+  int StackAdjust = CFARegisterOffset - 8;
+  if (RegOffsets.lookup(ARM::LR) != (-4 - StackAdjust)) {
+    DEBUG_WITH_TYPE("compact-unwind",
+                    llvm::dbgs()
+                        << "LR not saved as standard frame, StackAdjust="
+                        << StackAdjust
+                        << ", CFARegisterOffset=" << CFARegisterOffset
+                        << ", lr save at offset=" << RegOffsets[14] << "\n");
+    return CU::UNWIND_ARM_MODE_DWARF;
+  }
+  if (RegOffsets.lookup(ARM::R7) != (-8 - StackAdjust)) {
+    DEBUG_WITH_TYPE("compact-unwind",
+                    llvm::dbgs() << "r7 not saved as standard frame\n");
+    return CU::UNWIND_ARM_MODE_DWARF;
+  }
+  uint32_t CompactUnwindEncoding = CU::UNWIND_ARM_MODE_FRAME;
+
+  // If var-args are used, there may be a stack adjust required.
+  switch (StackAdjust) {
+  case 0:
+    break;
+  case 4:
+    CompactUnwindEncoding |= 0x00400000;
+    break;
+  case 8:
+    CompactUnwindEncoding |= 0x00800000;
+    break;
+  case 12:
+    CompactUnwindEncoding |= 0x00C00000;
+    break;
+  default:
+    DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs()
+                                          << ".cfi_def_cfa stack adjust ("
+                                          << StackAdjust << ") out of range\n");
+    return CU::UNWIND_ARM_MODE_DWARF;
+  }
+
+  // If r6 is saved, it must be right below r7.
+  static struct {
+    unsigned Reg;
+    unsigned Encoding;
+  } GPRCSRegs[] = {{ARM::R6, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R6},
+                   {ARM::R5, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R5},
+                   {ARM::R4, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R4},
+                   {ARM::R12, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R12},
+                   {ARM::R11, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R11},
+                   {ARM::R10, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R10},
+                   {ARM::R9, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R9},
+                   {ARM::R8, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R8}};
+
+  int CurOffset = -8 - StackAdjust;
+  for (auto CSReg : GPRCSRegs) {
+    auto Offset = RegOffsets.find(CSReg.Reg);
+    if (Offset == RegOffsets.end())
+      continue;
+
+    int RegOffset = Offset->second;
+    if (RegOffset != CurOffset - 4) {
+      DEBUG_WITH_TYPE("compact-unwind",
+                      llvm::dbgs() << MRI.getName(CSReg.Reg) << " saved at "
+                                   << RegOffset << " but only supported at "
+                                   << CurOffset << "\n");
+      return CU::UNWIND_ARM_MODE_DWARF;
+    }
+    CompactUnwindEncoding |= CSReg.Encoding;
+    CurOffset -= 4;
+  }
+
+  // If no floats saved, we are done.
+  if (FloatRegCount == 0)
+    return CompactUnwindEncoding;
+
+  // Switch mode to include D register saving.
+  CompactUnwindEncoding &= ~CU::UNWIND_ARM_MODE_MASK;
+  CompactUnwindEncoding |= CU::UNWIND_ARM_MODE_FRAME_D;
+
+  // FIXME: supporting more than 4 saved D-registers compactly would be trivial,
+  // but needs coordination with the linker and libunwind.
+  if (FloatRegCount > 4) {
+    DEBUG_WITH_TYPE("compact-unwind",
+                    llvm::dbgs() << "unsupported number of D registers saved ("
+                                 << FloatRegCount << ")\n");
+      return CU::UNWIND_ARM_MODE_DWARF;
+  }
+
+  // Floating point registers must either be saved sequentially, or we defer to
+  // DWARF. No gaps allowed here so check that each saved d-register is
+  // precisely where it should be.
+  static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
+  for (int Idx = FloatRegCount - 1; Idx >= 0; --Idx) {
+    auto Offset = RegOffsets.find(FPRCSRegs[Idx]);
+    if (Offset == RegOffsets.end()) {
+      DEBUG_WITH_TYPE("compact-unwind",
+                      llvm::dbgs() << FloatRegCount << " D-regs saved, but "
+                                   << MRI.getName(FPRCSRegs[Idx])
+                                   << " not saved\n");
+      return CU::UNWIND_ARM_MODE_DWARF;
+    } else if (Offset->second != CurOffset - 8) {
+      DEBUG_WITH_TYPE("compact-unwind",
+                      llvm::dbgs() << FloatRegCount << " D-regs saved, but "
+                                   << MRI.getName(FPRCSRegs[Idx])
+                                   << " saved at " << Offset->second
+                                   << ", expected at " << CurOffset - 8
+                                   << "\n");
+      return CU::UNWIND_ARM_MODE_DWARF;
+    }
+    CurOffset -= 8;
+  }
+
+  return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
+}
+
 static MachO::CPUSubTypeARM getMachOSubTypeFromArch(StringRef Arch) {
   unsigned AK = ARM::parseArch(Arch);
   switch (AK) {
@@ -821,7 +1038,7 @@ MCAsmBackend *llvm::createARMAsmBackend(
     llvm_unreachable("unsupported object format");
   case Triple::MachO: {
     MachO::CPUSubTypeARM CS = getMachOSubTypeFromArch(TheTriple.getArchName());
-    return new ARMAsmBackendDarwin(T, TheTriple, CS);
+    return new ARMAsmBackendDarwin(T, TheTriple, MRI, CS);
   }
   case Triple::COFF:
     assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h Wed Oct 28 17:56:36 2015
@@ -16,11 +16,12 @@ using namespace llvm;
 
 namespace {
 class ARMAsmBackendDarwin : public ARMAsmBackend {
+  const MCRegisterInfo &MRI;
 public:
   const MachO::CPUSubTypeARM Subtype;
   ARMAsmBackendDarwin(const Target &T, const Triple &TT,
-                      MachO::CPUSubTypeARM st)
-      : ARMAsmBackend(T, TT, /* IsLittleEndian */ true), Subtype(st) {
+                      const MCRegisterInfo &MRI, MachO::CPUSubTypeARM st)
+      : ARMAsmBackend(T, TT, /* IsLittleEndian */ true), MRI(MRI), Subtype(st) {
     HasDataInCodeSupport = true;
   }
 
@@ -28,6 +29,9 @@ public:
     return createARMMachObjectWriter(OS, /*Is64Bit=*/false, MachO::CPU_TYPE_ARM,
                                      Subtype);
   }
+
+  uint32_t generateCompactUnwindEncoding(
+      ArrayRef<MCCFIInstruction> Instrs) const override;
 };
 }
 

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp Wed Oct 28 17:56:36 2015
@@ -33,7 +33,8 @@ ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin(c
   SupportsDebugInformation = true;
 
   // Exceptions handling
-  ExceptionsType = ExceptionHandling::SjLj;
+  ExceptionsType = TheTriple.isWatchOS() ? ExceptionHandling::DwarfCFI
+                                         : ExceptionHandling::SjLj;
 
   UseIntegratedAssembler = true;
 }

Added: llvm/trunk/test/CodeGen/ARM/cfi-alignment.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/cfi-alignment.ll?rev=251573&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/cfi-alignment.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/cfi-alignment.ll Wed Oct 28 17:56:36 2015
@@ -0,0 +1,48 @@
+; RUN: llc -mtriple=thumbv7k-apple-watchos7.0 -o - %s | FileCheck %s
+
+; Since d11 doesn't get pushed with the aligned registers, its frameindex
+; shouldn't be modified to say it has been.
+
+define void @foo() {
+; CHECK-LABEL: foo:
+; CHECK: push {r7, lr}
+; CHECK: .cfi_offset r7, -8
+; CHECK: vpush {d11}
+; CHECK: vpush {d8, d9}
+; CHECK: .cfi_offset d11, -16
+; CHECK: .cfi_offset d9, -24
+; CHECK: .cfi_offset d8, -32
+  call void asm sideeffect "", "~{d8},~{d9},~{d11}"()
+  call void @bar()
+  ret void
+}
+
+define void @variadic_foo(i8, ...) {
+; CHECK-LABEL: variadic_foo:
+; CHECK: sub sp, #12
+; CHECK: push {r7, lr}
+; CHECK: .cfi_offset r7, -20
+; CHECK: sub sp, #4
+; CHECK: vpush {d11}
+; CHECK: vpush {d8, d9}
+; CHECK: .cfi_offset d11, -32
+; CHECK: .cfi_offset d9, -40
+; CHECK: .cfi_offset d8, -48
+  call void asm sideeffect "", "~{d8},~{d9},~{d11}"()
+  call void @llvm.va_start(i8* null)
+  call void @bar()
+  ret void
+}
+
+define void @test_maintain_stack_align() {
+; CHECK-LABEL: test_maintain_stack_align:
+; CHECK: push {r7, lr}
+; CHECK: vpush {d8, d9}
+; CHECK: sub sp, #8
+  call void asm sideeffect "", "~{d8},~{d9}"()
+  call void @bar()
+  ret void
+}
+
+declare void @bar()
+declare void @llvm.va_start(i8*) nounwind

Modified: llvm/trunk/test/CodeGen/ARM/eh-resume-darwin.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/eh-resume-darwin.ll?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/eh-resume-darwin.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/eh-resume-darwin.ll Wed Oct 28 17:56:36 2015
@@ -1,5 +1,5 @@
-; RUN: llc < %s -march=arm | FileCheck %s
-target triple = "armv6-apple-macosx10.6"
+; RUN: llc < %s -mtriple=armv7-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=IOS
+; RUN: llc < %s -mtriple=armv7k-apple-watchos -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=WATCHOS
 
 declare void @func()
 
@@ -19,4 +19,5 @@ lpad:
   resume { i8*, i32 } %exn
 }
 
-; CHECK: __Unwind_SjLj_Resume
+; IOS: __Unwind_SjLj_Resume
+; WATCHOS: __Unwind_Resume

Modified: llvm/trunk/test/CodeGen/ARM/v7k-abi-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/v7k-abi-align.ll?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/v7k-abi-align.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/v7k-abi-align.ll Wed Oct 28 17:56:36 2015
@@ -33,6 +33,8 @@ define void @test_dpr_unwind_align() {
 ; CHECK: push {r5, r6, r7, lr}
 ; CHECK-NOT: sub sp
 ; CHECK: vpush {d8, d9}
+; CHECK: .cfi_offset d9, -24
+; CHECK: .cfi_offset d8, -32
 ; [...]
 ; CHECK: bl _test_i64_align
 ; CHECK-NOT: add sp,
@@ -56,6 +58,8 @@ define void @test_dpr_unwind_align_manua
 ; CHECK: push.w {r8, r11}
 ; CHECK: sub sp, #4
 ; CHECK: vpush {d8, d9}
+; CHECK: .cfi_offset d9, -40
+; CHECK: .cfi_offset d8, -48
 ; [...]
 ; CHECK: bl _test_i64_align
 ; CHECK-NOT: add sp,
@@ -77,6 +81,8 @@ define void @test_dpr_unwind_align_just_
 ; CHECK: push {r4, r5, r6, r7, lr}
 ; CHECK: sub sp, #4
 ; CHECK: vpush {d8, d9}
+; CHECK: .cfi_offset d9, -32
+; CHECK: .cfi_offset d8, -40
 ; CHECK: sub sp, #8
 ; [...]
 ; CHECK: bl _test_i64_align

Modified: llvm/trunk/test/CodeGen/ARM/vfp-reg-stride.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vfp-reg-stride.ll?rev=251573&r1=251572&r2=251573&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/vfp-reg-stride.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/vfp-reg-stride.ll Wed Oct 28 17:56:36 2015
@@ -1,4 +1,5 @@
 ; RUN: llc -mcpu=swift -mtriple=thumbv7s-apple-ios -o - %s | FileCheck %s --check-prefix=CHECK-STRIDE4
+; RUN: llc -mcpu=swift -mtriple=thumbv7k-apple-watchos -o - %s | FileCheck %s --check-prefix=CHECK-STRIDE4-WATCH
 ; RUN: llc -mcpu=cortex-a57 -mtriple=thumbv7-linux-gnueabihf -o - %s | FileCheck %s --check-prefix=CHECK-GENERIC
 
 define void @test_reg_stride(double %a, double %b) {
@@ -6,6 +7,10 @@ define void @test_reg_stride(double %a,
 ; CHECK-STRIDE4-DAG: vmov d16, r
 ; CHECK-STRIDE4-DAG: vmov d18, r
 
+; CHECK-STRIDE4-WATCH-LABEL: test_reg_stride:
+; CHECK-STRIDE4-WATCH-DAG: vmov.f64 d16, d
+; CHECK-STRIDE4-WATCH-DAG: vmov.f64 d18, d
+
 ; CHECK-GENERIC-LABEL: test_reg_stride:
 ; CHECK-GENERIC-DAG: vmov.f64 d16, {{d[01]}}
 ; CHECK-GENERIC-DAG: vmov.f64 d17, {{d[01]}}
@@ -20,6 +25,10 @@ define void @test_stride_minsize(float %
 ; CHECK-STRIDE4: vmov d2, {{r[01]}}
 ; CHECK-STRIDE4: vmov d3, {{r[01]}}
 
+; CHECK-STRIDE4-WATCH-LABEL: test_stride_minsize:
+; CHECK-STRIDE4-WATCH-DAG: vmov.f32 s4, {{s[01]}}
+; CHECK-STRIDE4-WATCH-DAG: vmov.f32 s8, {{s[01]}}
+
 ; CHECK-GENERIC-LABEL: test_stride_minsize:
 ; CHECK-GENERIC-DAG: vmov.f32 s4, {{s[01]}}
 ; CHECK-GENERIC-DAG: vmov.f32 s6, {{s[01]}}

Added: llvm/trunk/test/MC/MachO/ARM/compact-unwind-armv7k.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/compact-unwind-armv7k.s?rev=251573&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/compact-unwind-armv7k.s (added)
+++ llvm/trunk/test/MC/MachO/ARM/compact-unwind-armv7k.s Wed Oct 28 17:56:36 2015
@@ -0,0 +1,124 @@
+@ RUN: llvm-mc -triple=thumbv7k-apple-watchos2.0.0 -filetype=obj -o %t < %s && llvm-objdump -unwind-info %t | FileCheck %s
+
+@ CHECK: Contents of __compact_unwind section:
+
+        .syntax unified
+        .align        2
+        .code        16
+
+@ CHECK-LABEL: start: {{.*}} _test_r4_r5_r6
+@ CHECK: compact encoding: 0x01000007
+        .thumb_func        _test_r4_r5_r6
+_test_r4_r5_r6:
+        .cfi_startproc
+        push        {r4, r5, r6, r7, lr}
+        add        r7, sp, #12
+        sub        sp, #16
+        .cfi_def_cfa r7, 8
+        .cfi_offset lr, -4
+        .cfi_offset r7, -8
+        .cfi_offset r6, -12
+        .cfi_offset r5, -16
+        .cfi_offset r4, -20
+        .cfi_endproc
+
+
+@ CHECK-LABEL: start: {{.*}} _test_r4_r5_r10_r11
+@ CHECK: compact encoding: 0x01000063
+        .thumb_func        _test_r4_r5_r10_r11
+_test_r4_r5_r10_r11:
+        .cfi_startproc
+        push        {r4, r5, r7, lr}
+        add        r7, sp, #8
+        .cfi_def_cfa r7, 8
+        .cfi_offset lr, -4
+        .cfi_offset r7, -8
+        .cfi_offset r5, -12
+        .cfi_offset r4, -16
+        push.w        {r10, r11}
+        .cfi_offset r11, -20
+        .cfi_offset r10, -24
+        .cfi_endproc
+
+
+@ CHECK-LABEL: start: {{.*}} _test_d8
+@ CHECK: compact encoding: 0x02000000
+        .thumb_func        _test_d8
+_test_d8:
+        .cfi_startproc
+        push        {r7, lr}
+        mov        r7, sp
+        .cfi_def_cfa r7, 8
+        .cfi_offset lr, -4
+        .cfi_offset r7, -8
+        vpush        {d8}
+        .cfi_offset d8, -16
+        .cfi_endproc
+
+
+@ CHECK-LABEL: start: {{.*}} _test_d8_d10_d12_d14
+@ CHECK: compact encoding: 0x02000300
+        .thumb_func        _test_d8_d10_d12_d14
+_test_d8_d10_d12_d14:
+        .cfi_startproc
+        push        {r7, lr}
+        mov        r7, sp
+        .cfi_def_cfa r7, 8
+        .cfi_offset lr, -4
+        .cfi_offset r7, -8
+        vpush        {d14}
+        vpush        {d12}
+        vpush        {d10}
+        vpush        {d8}
+        .cfi_offset d14, -16
+        .cfi_offset d12, -24
+        .cfi_offset d10, -32
+        .cfi_offset d8, -40
+        .cfi_endproc
+
+@ CHECK-LABEL: start: {{.*}} _test_varargs
+@ CHECK: compact encoding: 0x01c00001
+        .thumb_func        _test_varargs
+_test_varargs:
+        .cfi_startproc
+        sub        sp, #12
+        push        {r4, r7, lr}
+        add        r7, sp, #4
+        .cfi_def_cfa r7, 20
+        .cfi_offset lr, -16
+        .cfi_offset r7, -20
+        .cfi_offset r4, -24
+        add.w        r9, r7, #8
+        mov        r4, r0
+        stm.w        r9, {r1, r2, r3}
+        .cfi_endproc
+
+@ CHECK-LABEL: start: {{.*}} _test_missing_lr
+@ CHECK: compact encoding: 0x04000000
+        .thumb_func _test_missing_lr
+_test_missing_lr:
+        .cfi_startproc
+        push {r7}
+        .cfi_def_cfa r7, 4
+        .cfi_offset r7, -4
+        pop {r7}
+        bx lr
+        .cfi_endproc
+
+@ CHECK-LABEL: start: {{.*}} _test_swapped_offsets
+@ CHECK: compact encoding: 0x04000000
+        .thumb_func _test_swapped_offsets
+_test_swapped_offsets:
+        .cfi_startproc
+        push {r7, lr}
+        push {r10}
+        push {r4}
+        .cfi_def_cfa r7, 8
+        .cfi_offset lr, -4
+        .cfi_offset r7, -8
+        .cfi_offset r10, -12
+        .cfi_offset r4, -16
+        pop {r4}
+        pop {r10}
+        pop {r7, pc}
+        .cfi_endproc




More information about the llvm-commits mailing list