ARM MachO: sort out isTargetDarwin/isTargetIOS/... checks.
authorTim Northover <tnorthover@apple.com>
Mon, 6 Jan 2014 14:28:05 +0000 (14:28 +0000)
committerTim Northover <tnorthover@apple.com>
Mon, 6 Jan 2014 14:28:05 +0000 (14:28 +0000)
The ARM backend has been using most of the MachO related subtarget
checks almost interchangeably, and since the only target it's had to
run on has been IOS (which is all three of MachO, Darwin and IOS) it's
worked out OK so far.

But we'd like to support embedded targets under the "*-*-none-macho"
triple, which means everything starts falling apart and inconsistent
behaviours emerge.

This patch should pick a reasonably sensible set of behaviours for the
new triple (and any others that come along, with luck). Some choices
were debatable (notably FP == r7 or r11), but we can revisit those
later when deficiencies become apparent.

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

27 files changed:
lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMAsmPrinter.h
lib/Target/ARM/ARMBaseRegisterInfo.cpp
lib/Target/ARM/ARMFastISel.cpp
lib/Target/ARM/ARMFrameLowering.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMSelectionDAGInfo.cpp
lib/Target/ARM/ARMSubtarget.cpp
lib/Target/ARM/ARMSubtarget.h
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
lib/Target/ARM/Thumb1FrameLowering.cpp
lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
test/CodeGen/ARM/cse-ldrlit.ll
test/CodeGen/ARM/fast-isel-crash2.ll
test/CodeGen/ARM/fast-isel-frameaddr.ll
test/CodeGen/ARM/fold-stack-adjust.ll
test/CodeGen/ARM/interrupt-attr.ll
test/CodeGen/ARM/ldm.ll
test/CodeGen/ARM/memfunc.ll
test/CodeGen/ARM/none-macho.ll [new file with mode: 0644]

index 21efe10b1f0b5da50b3cdea7b199a330f4b42d65..296bb0dcee8faf856e8f9f729d1207bd69403eb0 100644 (file)
@@ -146,9 +146,9 @@ void ARMAsmPrinter::EmitXXStructor(const Constant *CV) {
   assert(GV && "C++ constructor pointer was not a GlobalValue!");
 
   const MCExpr *E = MCSymbolRefExpr::Create(getSymbol(GV),
-                                            (Subtarget->isTargetDarwin()
-                                             ? MCSymbolRefExpr::VK_None
-                                             : MCSymbolRefExpr::VK_ARM_TARGET1),
+                                            (Subtarget->isTargetELF()
+                                             ? MCSymbolRefExpr::VK_ARM_TARGET1
+                                             : MCSymbolRefExpr::VK_None),
                                             OutContext);
   
   OutStreamer.EmitValue(E, Size);
@@ -440,7 +440,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 }
 
 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
-  if (Subtarget->isTargetDarwin()) {
+  if (Subtarget->isTargetMachO()) {
     Reloc::Model RelocM = TM.getRelocationModel();
     if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
       // Declare all the text sections up front (before the DWARF sections
@@ -515,7 +515,7 @@ void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
 
 
 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
-  if (Subtarget->isTargetDarwin()) {
+  if (Subtarget->isTargetMachO()) {
     // All darwin targets use mach-o.
     const TargetLoweringObjectFileMachO &TLOFMacho =
       static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
@@ -783,7 +783,7 @@ getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
 
 MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
                                         unsigned char TargetFlags) {
-  bool isIndirect = Subtarget->isTargetDarwin() &&
+  bool isIndirect = Subtarget->isTargetMachO() &&
     (TargetFlags & ARMII::MO_NONLAZY) &&
     Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
   if (!isIndirect)
@@ -824,7 +824,7 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
 
     // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
     // flag the global as MO_NONLAZY.
-    unsigned char TF = Subtarget->isTargetDarwin() ? ARMII::MO_NONLAZY : 0;
+    unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0;
     MCSym = GetARMGVSymbol(GV, TF);
   } else if (ACPV->isMachineBasicBlock()) {
     const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
@@ -1536,7 +1536,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   case ARM::TRAP: {
     // Non-Darwin binutils don't yet support the "trap" mnemonic.
     // FIXME: Remove this special case when they do.
-    if (!Subtarget->isTargetDarwin()) {
+    if (!Subtarget->isTargetMachO()) {
       //.long 0xe7ffdefe @ trap
       uint32_t Val = 0xe7ffdefeUL;
       OutStreamer.AddComment("trap");
@@ -1555,7 +1555,7 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
   case ARM::tTRAP: {
     // Non-Darwin binutils don't yet support the "trap" mnemonic.
     // FIXME: Remove this special case when they do.
-    if (!Subtarget->isTargetDarwin()) {
+    if (!Subtarget->isTargetMachO()) {
       //.short 57086 @ trap
       uint16_t Val = 0xdefe;
       OutStreamer.AddComment("trap");
index 7006400107127d4d6c2a3b17b263813a1788a503..d7136505e491fb5b9040539baef3ef507b91e1f8 100644 (file)
@@ -103,7 +103,7 @@ public:
 
   virtual unsigned getISAEncoding() LLVM_OVERRIDE {
     // ARM/Darwin adds ISA to the DWARF info for each function.
-    if (!Subtarget->isTargetDarwin())
+    if (!Subtarget->isTargetMachO())
       return 0;
     return Subtarget->isThumb() ?
       ARM::DW_ISA_ARM_thumb : ARM::DW_ISA_ARM_arm;
index 8717dc0cde90f99ba050b943b19b85d093885b9f..79f975e3ae24604d539f6158e533b9821b59314a 100644 (file)
@@ -45,7 +45,7 @@ using namespace llvm;
 
 ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMSubtarget &sti)
   : ARMGenRegisterInfo(ARM::LR, 0, 0, ARM::PC), STI(sti),
-    FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11),
+    FramePtr((STI.isTargetMachO() || STI.isThumb()) ? ARM::R7 : ARM::R11),
     BasePtr(ARM::R6) {
 }
 
index 5bb4ba9bd2d20c686d68e1c162ae6436b136a8cd..32b69291663d35d498b99fdd61e6cd8c6df37345 100644 (file)
@@ -675,18 +675,18 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) {
     (const TargetRegisterClass*)&ARM::GPRRegClass;
   unsigned DestReg = createResultReg(RC);
 
-  // FastISel TLS support on non-Darwin is broken, punt to SelectionDAG.
+  // FastISel TLS support on non-MachO is broken, punt to SelectionDAG.
   const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
   bool IsThreadLocal = GVar && GVar->isThreadLocal();
-  if (!Subtarget->isTargetDarwin() && IsThreadLocal) return 0;
+  if (!Subtarget->isTargetMachO() && IsThreadLocal) return 0;
 
   // Use movw+movt when possible, it avoids constant pool entries.
   // Non-darwin targets only support static movt relocations in FastISel.
   if (Subtarget->useMovt() &&
-      (Subtarget->isTargetDarwin() || RelocM == Reloc::Static)) {
+      (Subtarget->isTargetMachO() || RelocM == Reloc::Static)) {
     unsigned Opc;
     unsigned char TF = 0;
-    if (Subtarget->isTargetDarwin())
+    if (Subtarget->isTargetMachO())
       TF = ARMII::MO_NONLAZY;
 
     switch (RelocM) {
@@ -3144,7 +3144,7 @@ namespace llvm {
     const ARMSubtarget *Subtarget = &TM.getSubtarget<ARMSubtarget>();
     // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl.
     bool UseFastISel = false;
-    UseFastISel |= Subtarget->isTargetIOS() && !Subtarget->isThumb1Only();
+    UseFastISel |= Subtarget->isTargetMachO() && !Subtarget->isThumb1Only();
     UseFastISel |= Subtarget->isTargetLinux() && !Subtarget->isThumb();
     UseFastISel |= Subtarget->isTargetNaCl() && !Subtarget->isThumb();
 
index ceff79068521c8713059a0323f5d7487d81d22a5..63f1577821477e46df07593e829754cb16913a98 100644 (file)
@@ -195,7 +195,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
     case ARM::R12:
       if (Reg == FramePtr)
         FramePtrSpillFI = FI;
-      if (STI.isTargetIOS())
+      if (STI.isTargetMachO())
         GPRCS2Size += 4;
       else
         GPRCS1Size += 4;
@@ -454,7 +454,7 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
     // Jump to label or value in register.
     if (RetOpcode == ARM::TCRETURNdi) {
       unsigned TCOpcode = STI.isThumb() ?
-               (STI.isTargetIOS() ? ARM::tTAILJMPd : ARM::tTAILJMPdND) :
+               (STI.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND) :
                ARM::TAILJMPd;
       MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
       if (JumpTarget.isGlobal())
@@ -599,7 +599,7 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
     unsigned LastReg = 0;
     for (; i != 0; --i) {
       unsigned Reg = CSI[i-1].getReg();
-      if (!(Func)(Reg, STI.isTargetIOS())) continue;
+      if (!(Func)(Reg, STI.isTargetMachO())) continue;
 
       // D-registers in the aligned area DPRCS2 are NOT spilled here.
       if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -672,7 +672,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
     bool DeleteRet = false;
     for (; i != 0; --i) {
       unsigned Reg = CSI[i-1].getReg();
-      if (!(Func)(Reg, STI.isTargetIOS())) continue;
+      if (!(Func)(Reg, STI.isTargetMachO())) continue;
 
       // The aligned reloads from area DPRCS2 are not inserted here.
       if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -1221,7 +1221,7 @@ ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
     if (Spilled) {
       NumGPRSpills++;
 
-      if (!STI.isTargetIOS()) {
+      if (!STI.isTargetMachO()) {
         if (Reg == ARM::LR)
           LRSpilled = true;
         CS1Spilled = true;
@@ -1243,7 +1243,7 @@ ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
         break;
       }
     } else {
-      if (!STI.isTargetIOS()) {
+      if (!STI.isTargetMachO()) {
         UnspilledCS1GPRs.push_back(Reg);
         continue;
       }
index 527bc399980a695d44536bd61313369d0ff31a84..8b2366336dbfbce2f9ed6b92adbf4e7969745313 100644 (file)
@@ -161,7 +161,7 @@ void ARMTargetLowering::addQRTypeForNEON(MVT VT) {
 }
 
 static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) {
-  if (TM.getSubtarget<ARMSubtarget>().isTargetDarwin())
+  if (TM.getSubtarget<ARMSubtarget>().isTargetMachO())
     return new TargetLoweringObjectFileMachO();
 
   return new ARMElfTargetObjectFile();
@@ -175,7 +175,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
 
   setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
 
-  if (Subtarget->isTargetIOS()) {
+  if (Subtarget->isTargetMachO()) {
     // Uses VFP for Thumb libfuncs if available.
     if (Subtarget->isThumb() && Subtarget->hasVFP2() &&
         Subtarget->hasARMOps()) {
@@ -258,7 +258,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setLibcallName(RTLIB::SRL_I128, 0);
   setLibcallName(RTLIB::SRA_I128, 0);
 
-  if (Subtarget->isAAPCS_ABI() && !Subtarget->isTargetDarwin()) {
+  if (Subtarget->isAAPCS_ABI() && !Subtarget->isTargetMachO()) {
     // Double-precision floating-point arithmetic helper functions
     // RTABI chapter 4.1.2, Table 2
     setLibcallName(RTLIB::ADD_F64, "__aeabi_dadd");
@@ -733,8 +733,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
   setOperationAction(ISD::STACKSAVE,          MVT::Other, Expand);
   setOperationAction(ISD::STACKRESTORE,       MVT::Other, Expand);
 
-  if (!Subtarget->isTargetDarwin()) {
-    // Non-Darwin platforms may return values in these registers via the
+  if (!Subtarget->isTargetMachO()) {
+    // Non-MachO platforms may return values in these registers via the
     // personality function.
     setExceptionPointerRegister(ARM::R0);
     setExceptionSelectorRegister(ARM::R1);
@@ -1694,14 +1694,14 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     const GlobalValue *GV = G->getGlobal();
     isDirect = true;
     bool isExt = GV->isDeclaration() || GV->isWeakForLinker();
-    bool isStub = (isExt && Subtarget->isTargetDarwin()) &&
+    bool isStub = (isExt && Subtarget->isTargetMachO()) &&
                    getTargetMachine().getRelocationModel() != Reloc::Static;
     isARMFunc = !Subtarget->isThumb() || isStub;
     // ARM call to a local ARM function is predicable.
     isLocalARMFunc = !Subtarget->isThumb() && (!isExt || !ARMInterworking);
     // tBX takes a register source operand.
     if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
-      assert(Subtarget->isTargetDarwin() && "WrapperPIC use on non-Darwin?");
+      assert(Subtarget->isTargetMachO() && "WrapperPIC use on non-MachO?");
       Callee = DAG.getNode(ARMISD::WrapperPIC, dl, getPointerTy(),
                            DAG.getTargetGlobalAddress(GV, dl, getPointerTy()));
     } else {
@@ -1714,7 +1714,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
     }
   } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
     isDirect = true;
-    bool isStub = Subtarget->isTargetDarwin() &&
+    bool isStub = Subtarget->isTargetMachO() &&
                   getTargetMachine().getRelocationModel() != Reloc::Static;
     isARMFunc = !Subtarget->isThumb() || isStub;
     // tBX takes a register source operand.
@@ -3778,7 +3778,7 @@ SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
   EVT VT = Op.getValueType();
   SDLoc dl(Op);  // FIXME probably not meaningful
   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
-  unsigned FrameReg = (Subtarget->isThumb() || Subtarget->isTargetDarwin())
+  unsigned FrameReg = (Subtarget->isThumb() || Subtarget->isTargetMachO())
     ? ARM::R7 : ARM::R11;
   SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
   while (Depth--)
@@ -6065,7 +6065,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::ConstantPool:  return LowerConstantPool(Op, DAG);
   case ISD::BlockAddress:  return LowerBlockAddress(Op, DAG);
   case ISD::GlobalAddress:
-    return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) :
+    return Subtarget->isTargetMachO() ? LowerGlobalAddressDarwin(Op, DAG) :
       LowerGlobalAddressELF(Op, DAG);
   case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
   case ISD::SELECT:        return LowerSELECT(Op, DAG);
index aaa4ee07f163c263dd0e6c6c9e8663d72495c5e3..cbf67c96458222a1437745a19d57e9b75e6d37be 100644 (file)
@@ -260,6 +260,8 @@ def IsARM            : Predicate<"!Subtarget->isThumb()">,
                                  AssemblerPredicate<"!ModeThumb", "arm-mode">;
 def IsIOS            : Predicate<"Subtarget->isTargetIOS()">;
 def IsNotIOS         : Predicate<"!Subtarget->isTargetIOS()">;
+def IsMachO          : Predicate<"Subtarget->isTargetMachO()">;
+def IsNotMachO       : Predicate<"!Subtarget->isTargetMachO()">;
 def IsNaCl           : Predicate<"Subtarget->isTargetNaCl()">;
 def UseNaClTrap      : Predicate<"Subtarget->useNaClTrap()">,
                                  AssemblerPredicate<"FeatureNaClTrap", "NaCl">;
index f6d233a39c5accdc930234af4ca68432a751cb05..2130145bef2dcda8bff15934790e360bb843bde8 100644 (file)
@@ -545,15 +545,15 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
                      (tBX GPR:$dst, (ops 14, zero_reg))>,
                      Requires<[IsThumb]>, Sched<[WriteBr]>;
   }
-  // tTAILJMPd: IOS version uses a Thumb2 branch (no Thumb1 tail calls
-  // on IOS), so it's in ARMInstrThumb2.td.
-  // Non-IOS version:
+  // tTAILJMPd: MachO version uses a Thumb2 branch (no Thumb1 tail calls
+  // on MachO), so it's in ARMInstrThumb2.td.
+  // Non-MachO version:
   let Uses = [SP] in {
     def tTAILJMPdND : tPseudoExpand<(outs),
                    (ins t_brtarget:$dst, pred:$p),
                    4, IIC_Br, [],
                    (tB t_brtarget:$dst, pred:$p)>,
-                 Requires<[IsThumb, IsNotIOS]>, Sched<[WriteBr]>;
+                 Requires<[IsThumb, IsNotMachO]>, Sched<[WriteBr]>;
   }
 }
 
index 10ba894329e78158d7395d79cfa164a26f607103..73dc071e773334bec168d5eccc60d82f72b074e0 100644 (file)
@@ -3549,7 +3549,7 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
   let AsmMatchConverter = "cvtThumbBranches";
 }
 
-// Tail calls. The IOS version of thumb tail calls uses a t2 branch, so
+// Tail calls. The MachO version of thumb tail calls uses a t2 branch, so
 // it goes here.
 let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
   // IOS version.
@@ -3558,7 +3558,7 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
                    (ins uncondbrtarget:$dst, pred:$p),
                    4, IIC_Br, [],
                    (t2B uncondbrtarget:$dst, pred:$p)>,
-                 Requires<[IsThumb2, IsIOS]>, Sched<[WriteBr]>;
+                 Requires<[IsThumb2, IsMachO]>, Sched<[WriteBr]>;
 }
 
 // IT block
index 00e44f5273fe1a0afb8a6e1ae25645be535620ab..ba3cf4d92ed8cccf49862f17e812951a7f5e6e01 100644 (file)
@@ -145,8 +145,8 @@ EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl,
                         SDValue Src, SDValue Size,
                         unsigned Align, bool isVolatile,
                         MachinePointerInfo DstPtrInfo) const {
-  // Use default for non-AAPCS (or Darwin) subtargets
-  if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetDarwin())
+  // Use default for non-AAPCS (or MachO) subtargets
+  if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetMachO())
     return SDValue();
 
   const ARMTargetLowering &TLI =
index 81fdbfd226c3dbf352568b5ec2c8fcab6e311d6a..547c69a6fd9a82129843cfb419a80ce7663e46fc 100644 (file)
@@ -196,6 +196,7 @@ void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) {
     case Triple::EABIHF:
     case Triple::GNUEABI:
     case Triple::GNUEABIHF:
+    case Triple::MachO:
       TargetABI = ARM_ABI_AAPCS;
       break;
     default:
@@ -212,12 +213,11 @@ void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) {
 
   UseMovt = hasV6T2Ops() && ArmUseMOVT;
 
-  if (!isTargetIOS()) {
-    IsR9Reserved = ReserveR9;
-  } else {
+  if (isTargetMachO()) {
     IsR9Reserved = ReserveR9 | !HasV6Ops;
-    SupportsTailCall = !getTargetTriple().isOSVersionLT(5, 0);
-  }
+    SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0);
+  } else
+    IsR9Reserved = ReserveR9;
 
   if (!isThumb() || hasThumb2())
     PostRAScheduler = true;
@@ -239,7 +239,7 @@ void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) {
       // The above behavior is consistent with GCC.
       AllowsUnalignedMem = (
           (hasV7Ops() && (isTargetLinux() || isTargetNaCl())) ||
-          (hasV6Ops() && isTargetDarwin()));
+          (hasV6Ops() && isTargetMachO()));
       break;
     case StrictAlign:
       AllowsUnalignedMem = false;
@@ -281,7 +281,7 @@ ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
   if (GV->isDeclaration() && !GV->isMaterializable())
     isDecl = true;
 
-  if (!isTargetDarwin()) {
+  if (!isTargetMachO()) {
     // Extra load is needed for all externally visible.
     if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
       return false;
index d1433ecade54b0f809c62893766d9845c538eee2..3a9f940381d029cb753819b9b19ddda9f8a83f22 100644 (file)
@@ -311,7 +311,10 @@ public:
   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
   bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
+
   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
+  bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
+
   // ARM EABI is the bare-metal EABI described in ARM ABI documents and
   // can be accessed via -target arm-none-eabi. This is NOT GNUEABI.
   // FIXME: Add a flag for bare-metal for that target and set Triple::EABI
index 33274bfd0faec96ff50d8920199145b4bffc2609..b57527c91e3802a99fee9a84b5ecaaed83ed7ddc 100644 (file)
@@ -26,6 +26,7 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
 #include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -39,6 +40,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/SourceMgr.h"
index 5615b808fc1122b4907e1e74c2b5758e3e66de7f..fecab9f5d49b72afbfe60f9857f975288e2e1c39 100644 (file)
@@ -665,7 +665,7 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T,
                                         StringRef TT, StringRef CPU) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin()) {
+  if (TheTriple.isOSBinFormatMachO()) {
     MachO::CPUSubTypeARM CS =
       StringSwitch<MachO::CPUSubTypeARM>(TheTriple.getArchName())
       .Cases("armv4t", "thumbv4t", MachO::CPU_SUBTYPE_ARM_V4T)
index 4382d0d9714447f003a7f5c6257a9579a388028b..25a3d4df43556ad07b893b98d001addb4357bab6 100644 (file)
@@ -56,9 +56,9 @@ public:
   bool isThumb2() const {
     return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) != 0;
   }
-  bool isTargetDarwin() const {
+  bool isTargetMachO() const {
     Triple TT(STI.getTargetTriple());
-       return TT.isOSDarwin();
+    return TT.isOSBinFormatMachO();
   }
 
   unsigned getMachineSoImmOpValue(unsigned SoImm) const;
@@ -915,7 +915,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
     switch (ARM16Expr->getKind()) {
     default: llvm_unreachable("Unsupported ARMFixup");
     case ARMMCExpr::VK_ARM_HI16:
-      if (!isTargetDarwin() && EvaluateAsPCRel(E))
+      if (!isTargetMachO() && EvaluateAsPCRel(E))
         Kind = MCFixupKind(isThumb2()
                            ? ARM::fixup_t2_movt_hi16_pcrel
                            : ARM::fixup_arm_movt_hi16_pcrel);
@@ -925,7 +925,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
                            : ARM::fixup_arm_movt_hi16);
       break;
     case ARMMCExpr::VK_ARM_LO16:
-      if (!isTargetDarwin() && EvaluateAsPCRel(E))
+      if (!isTargetMachO() && EvaluateAsPCRel(E))
         Kind = MCFixupKind(isThumb2()
                            ? ARM::fixup_t2_movw_lo16_pcrel
                            : ARM::fixup_arm_movw_lo16_pcrel);
@@ -942,7 +942,7 @@ ARMMCCodeEmitter::getHiLo16ImmOpValue(const MCInst &MI, unsigned OpIdx,
   // it's just a plain immediate expression, and those evaluate to
   // the lower 16 bits of the expression regardless of whether
   // we have a movt or a movw.
-  if (!isTargetDarwin() && EvaluateAsPCRel(E))
+  if (!isTargetMachO() && EvaluateAsPCRel(E))
     Kind = MCFixupKind(isThumb2()
                        ? ARM::fixup_t2_movw_lo16_pcrel
                        : ARM::fixup_arm_movw_lo16_pcrel);
index 400dab71486f6995ab2ac108ddbed9b6a1b7ced6..04376b8e46b4aa02b623dfaee78d8fe105f4fd01 100644 (file)
@@ -212,7 +212,7 @@ static MCRegisterInfo *createARMMCRegisterInfo(StringRef Triple) {
 static MCAsmInfo *createARMMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin())
+  if (TheTriple.isOSBinFormatMachO())
     return new ARMMCAsmInfoDarwin();
 
   return new ARMELFMCAsmInfo();
@@ -240,7 +240,7 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
                                     bool NoExecStack) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin())
+  if (TheTriple.isOSBinFormatMachO())
     return createMachOStreamer(Ctx, MAB, OS, Emitter, false);
 
   if (TheTriple.isOSWindows()) {
index 0a05c0b84953fd0f2f38cb09db540bd0387c6044..d8546dac31d083003935878e6749c93ec8a57da3 100644 (file)
@@ -135,7 +135,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
     case ARM::R11:
       if (Reg == FramePtr)
         FramePtrSpillFI = FI;
-      if (STI.isTargetIOS())
+      if (STI.isTargetMachO())
         GPRCS2Size += 4;
       else
         GPRCS1Size += 4;
index ab95eb6d3324e8cb58c338d2965e8eba24ad94aa..2cf6381198e121e78dfc257aeb9482683da41be0 100644 (file)
@@ -803,7 +803,7 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
                                            StringRef CPU) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
+  if (TheTriple.isOSBinFormatMachO())
     return new DarwinX86_32AsmBackend(T, MRI, CPU,
                                       TheTriple.isMacOSX() &&
                                       !TheTriple.isMacOSXVersionLT(10, 7));
@@ -821,7 +821,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
                                            StringRef CPU) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) {
+  if (TheTriple.isOSBinFormatMachO()) {
     MachO::CPUSubTypeX86 CS =
         StringSwitch<MachO::CPUSubTypeX86>(TheTriple.getArchName())
             .Case("x86_64h", MachO::CPU_SUBTYPE_X86_64_H)
index 09803f372f57392212b850d3b4691550b946f4c9..9d5ff1027cd23a1256a26dbf46c8d0e2e2124118 100644 (file)
@@ -268,7 +268,7 @@ static MCAsmInfo *createX86MCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
   bool is64Bit = TheTriple.getArch() == Triple::x86_64;
 
   MCAsmInfo *MAI;
-  if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO) {
+  if (TheTriple.isOSBinFormatMachO()) {
     if (is64Bit)
       MAI = new X86_64MCAsmInfoDarwin(TheTriple);
     else
@@ -362,7 +362,7 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
                                     bool NoExecStack) {
   Triple TheTriple(TT);
 
-  if (TheTriple.isOSDarwin() || TheTriple.getEnvironment() == Triple::MachO)
+  if (TheTriple.isOSBinFormatMachO())
     return createMachOStreamer(Ctx, MAB, _OS, _Emitter, RelaxAll);
 
   if (TheTriple.isOSWindows() && TheTriple.getEnvironment() != Triple::ELF)
index c59b4c06f0ec979ab060f06ff612493b19d7ac5f..ea8c0ca8560d7c4fd60b883d285f4a2599b6a494 100644 (file)
@@ -1,9 +1,9 @@
-; RUN: llc -mtriple=thumbv6m-apple-darwin-eabi -relocation-model=pic -o -  %s | FileCheck %s --check-prefix=CHECK-THUMB-PIC
-; RUN: llc -mtriple=arm-apple-darwin-eabi -relocation-model=pic -o -  %s | FileCheck %s --check-prefix=CHECK-ARM-PIC
-; RUN: llc -mtriple=thumbv6m-apple-darwin-eabi -relocation-model=dynamic-no-pic -o -  %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
-; RUN: llc -mtriple=arm-apple-darwin-eabi -relocation-model=dynamic-no-pic -o -  %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
-; RUN: llc -mtriple=thumbv6m-apple-darwin-eabi -relocation-model=static -o -  %s | FileCheck %s --check-prefix=CHECK-STATIC
-; RUN: llc -mtriple=arm-apple-darwin-eabi -relocation-model=static -o -  %s | FileCheck %s --check-prefix=CHECK-STATIC
+; RUN: llc -mtriple=thumbv6m-apple-none-macho -relocation-model=pic -o -  %s | FileCheck %s --check-prefix=CHECK-THUMB-PIC
+; RUN: llc -mtriple=arm-apple-none-macho -relocation-model=pic -o -  %s | FileCheck %s --check-prefix=CHECK-ARM-PIC
+; RUN: llc -mtriple=thumbv6m-apple-none-macho -relocation-model=dynamic-no-pic -o -  %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
+; RUN: llc -mtriple=arm-apple-none-macho -relocation-model=dynamic-no-pic -o -  %s | FileCheck %s --check-prefix=CHECK-DYNAMIC
+; RUN: llc -mtriple=thumbv6m-apple-none-macho -relocation-model=static -o -  %s | FileCheck %s --check-prefix=CHECK-STATIC
+; RUN: llc -mtriple=arm-apple-none-macho -relocation-model=static -o -  %s | FileCheck %s --check-prefix=CHECK-STATIC
 @var = global [16 x i32] zeroinitializer
 
 declare void @bar(i32*)
index d606877673dc9143a2780de90a619f5a2266b99e..cccd9eb951ba2014b12783cd9a410d93d26471bb 100644 (file)
@@ -1,5 +1,5 @@
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=thumbv7-apple-darwin
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=thumbv7-linux-gnueabi
+; RUN: llc < %s -O0 -verify-machineinstrs -mtriple=thumbv7-apple-darwin
+; RUN: llc < %s -O0 -verify-machineinstrs -mtriple=armv7-linux-gnueabi
 ; rdar://9515076
 ; (Make sure this doesn't crash.)
 
index 8542bb5e27d21e0a5506e76b8955b62fee7a6b91..93cdbbbbd86ebb727e7d90326510b835d54f7013 100644 (file)
@@ -1,6 +1,6 @@
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=armv7-apple-darwin | FileCheck %s --check-prefix=DARWIN-ARM
+; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=DARWIN-ARM
 ; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=armv7-linux-gnueabi | FileCheck %s --check-prefix=LINUX-ARM
-; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefix=DARWIN-THUMB2
+; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=DARWIN-THUMB2
 ; RUN: llc < %s -O0 -verify-machineinstrs -fast-isel-abort -mtriple=thumbv7-linux-gnueabi | FileCheck %s --check-prefix=LINUX-THUMB2
 
 define i8* @frameaddr_index0() nounwind {
@@ -34,14 +34,12 @@ entry:
 ; DARWIN-ARM-LABEL: frameaddr_index1:
 ; DARWIN-ARM: push {r7}
 ; DARWIN-ARM: mov r7, sp
-; DARWIN-ARM: mov r0, r7
-; DARWIN-ARM: ldr r0, [r0]
+; DARWIN-ARM: ldr r0, [r7]
 
 ; DARWIN-THUMB2-LABEL: frameaddr_index1:
 ; DARWIN-THUMB2: str r7, [sp, #-4]!
 ; DARWIN-THUMB2: mov r7, sp
-; DARWIN-THUMB2: mov r0, r7
-; DARWIN-THUMB2: ldr r0, [r0]
+; DARWIN-THUMB2: ldr r0, [r7]
 
 ; LINUX-ARM-LABEL: frameaddr_index1:
 ; LINUX-ARM: push {r11}
@@ -63,16 +61,14 @@ entry:
 ; DARWIN-ARM-LABEL: frameaddr_index3:
 ; DARWIN-ARM: push {r7}
 ; DARWIN-ARM: mov r7, sp
-; DARWIN-ARM: mov r0, r7
-; DARWIN-ARM: ldr r0, [r0]
+; DARWIN-ARM: ldr r0, [r7]
 ; DARWIN-ARM: ldr r0, [r0]
 ; DARWIN-ARM: ldr r0, [r0]
 
 ; DARWIN-THUMB2-LABEL: frameaddr_index3:
 ; DARWIN-THUMB2: str r7, [sp, #-4]!
 ; DARWIN-THUMB2: mov r7, sp
-; DARWIN-THUMB2: mov r0, r7
-; DARWIN-THUMB2: ldr r0, [r0]
+; DARWIN-THUMB2: ldr r0, [r7]
 ; DARWIN-THUMB2: ldr r0, [r0]
 ; DARWIN-THUMB2: ldr r0, [r0]
 
index 67fd129fd1c90ff7cc15863213dbd4a52f4a536d..81d94d16c15254157b380d139d0bf001647a9ccc 100644 (file)
@@ -1,5 +1,5 @@
-; RUN: llc -mtriple=thumbv7-apple-darwin-eabi < %s | FileCheck %s
-; RUN: llc -mtriple=thumbv6m-apple-darwin-eabi -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-T1
+; RUN: llc -mtriple=thumbv7-apple-none-macho < %s | FileCheck %s
+; RUN: llc -mtriple=thumbv6m-apple-none-macho -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-T1
 ; RUN: llc -mtriple=thumbv7-apple-darwin-ios -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-IOS
 
 
@@ -11,11 +11,11 @@ declare void @bar(i8*)
 
 define void @check_simple() minsize {
 ; CHECK-LABEL: check_simple:
-; CHECK: push.w {r7, r8, r9, r10, r11, lr}
+; CHECK: push {r3, r4, r5, r6, r7, lr}
 ; CHECK-NOT: sub sp, sp,
 ; ...
 ; CHECK-NOT: add sp, sp,
-; CHECK: pop.w {r0, r1, r2, r3, r11, pc}
+; CHECK: pop {r0, r1, r2, r3, r7, pc}
 
 ; CHECK-T1-LABEL: check_simple:
 ; CHECK-T1: push {r3, r4, r5, r6, r7, lr}
@@ -43,11 +43,11 @@ define void @check_simple() minsize {
 
 define void @check_simple_too_big() minsize {
 ; CHECK-LABEL: check_simple_too_big:
-; CHECK: push.w {r11, lr}
+; CHECK: push {r7, lr}
 ; CHECK: sub sp,
 ; ...
 ; CHECK: add sp,
-; CHECK: pop.w {r11, pc}
+; CHECK: pop {r7, pc}
   %var = alloca i8, i32 64
   call void @bar(i8* %var)
   ret void
@@ -92,16 +92,16 @@ define void @check_vfp_fold() minsize {
 ; folded in except that doing so would clobber the value being returned.
 define i64 @check_no_return_clobber() minsize {
 ; CHECK-LABEL: check_no_return_clobber:
-; CHECK: push.w {r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
+; CHECK: push {r1, r2, r3, r4, r5, r6, r7, lr}
 ; CHECK-NOT: sub sp,
 ; ...
-; CHECK: add sp, #40
-; CHECK: pop.w {r11, pc}
+; CHECK: add sp, #24
+; CHECK: pop {r7, pc}
 
   ; Just to keep iOS FileCheck within previous function:
 ; CHECK-IOS-LABEL: check_no_return_clobber:
 
-  %var = alloca i8, i32 40
+  %var = alloca i8, i32 20
   call void @bar(i8* %var)
   ret i64 0
 }
@@ -161,4 +161,4 @@ end:
   ; We want the epilogue to be the only thing in a basic block so that we hit
   ; the correct edge-case (first inst in block is correct one to adjust).
   ret void
-}
\ No newline at end of file
+}
index 217fd696237e30daf1723030061ae7cb00d0fb9e..10d5c00a858afe9d68bc720d0027b5a9535c5125 100644 (file)
@@ -1,6 +1,6 @@
 ; RUN: llc -mtriple=arm-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A %s
 ; RUN: llc -mtriple=thumb-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A-THUMB %s
-; RUN: llc -mtriple=thumb-apple-darwin -mcpu=cortex-m3 -o - %s | FileCheck --check-prefix=CHECK-M %s
+; RUN: llc -mtriple=thumb-apple-none-macho -mcpu=cortex-m3 -o - %s | FileCheck --check-prefix=CHECK-M %s
 
 declare arm_aapcscc void @bar()
 
@@ -34,10 +34,11 @@ define arm_aapcscc void @irq_fn() alignstack(8) "interrupt"="IRQ" {
 
   ; Normal AAPCS function (r0-r3 pushed onto stack by hardware, lr set to
   ; appropriate sentinel so no special return needed).
+; CHECK-M-LABEL: irq_fn:
 ; CHECK-M: push {r4, r7, lr}
 ; CHECK-M: add r7, sp, #4
-; CHECK-M: sub sp, #4
 ; CHECK-M: mov r4, sp
+; CHECK-M: bic r4, r4, #7
 ; CHECK-M: mov sp, r4
 ; CHECK-M: blx _bar
 ; CHECK-M: subs r4, r7, #4
@@ -61,6 +62,8 @@ define arm_aapcscc void @fiq_fn() alignstack(8) "interrupt"="FIQ" {
 ; CHECK-A: pop {r0, r1, r2, r3, r4, r5, r6, r7, r11, lr}
 ; CHECK-A: subs pc, lr, #4
 
+; CHECK-A-THUMB-LABEL: fiq_fn:
+; CHECK-M-LABEL: fiq_fn:
   %val = load volatile [16 x i32]* @bigvar
   store volatile [16 x i32] %val, [16 x i32]* @bigvar
   ret void
index d5b805c721b7bb9b9ba62fbffe42cee32115feba..3977da6da9cb6b786940fc6dee351116730d650e 100644 (file)
@@ -1,5 +1,5 @@
-; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s
-; RUN: llc < %s -mtriple=armv4t-apple-darwin | FileCheck %s -check-prefix=V4T
+; RUN: llc < %s -mtriple=armv7-apple-ios3.0 | FileCheck %s
+; RUN: llc < %s -mtriple=armv4t-apple-ios3.0 | FileCheck %s -check-prefix=V4T
 
 @X = external global [0 x i32]          ; <[0 x i32]*> [#uses=5]
 
index a724080b74ca3c60df8bf03f7330ae0118f4747e..8d3800b43c14172044943f31e04cfbd8f7d0723f 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: llc < %s -mtriple=armv7-apple-ios -o - | FileCheck %s
-; RUN: llc < %s -mtriple=thumbv7m-darwin-eabi -o - | FileCheck %s --check-prefix=DARWIN
+; RUN: llc < %s -mtriple=thumbv7m-none-macho -o - | FileCheck %s --check-prefix=DARWIN
 ; RUN: llc < %s -mtriple=arm-none-eabi -o - | FileCheck --check-prefix=EABI %s
 ; RUN: llc < %s -mtriple=arm-none-eabihf -o - | FileCheck --check-prefix=EABI %s
 
diff --git a/test/CodeGen/ARM/none-macho.ll b/test/CodeGen/ARM/none-macho.ll
new file mode 100644 (file)
index 0000000..2795b8c
--- /dev/null
@@ -0,0 +1,101 @@
+; RUN: llc -mtriple=thumbv7m-none-macho %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NON-FAST
+; RUN: llc -mtriple=thumbv7m-none-macho -O0 %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s
+; RUN: llc -mtriple=thumbv7m-none-macho -filetype=obj %s -o /dev/null
+
+  ; Bare-metal should probably "declare" segments just like normal MachO
+; CHECK: __picsymbolstub4
+; CHECK: __StaticInit
+; CHECK: __text
+
+@var = external global i32
+
+define i32 @test_litpool() minsize {
+; CHECK-LABEL: test_litpool:
+  %val = load i32* @var
+  ret i32 %val
+
+  ; Lit-pool entries need to produce a "$non_lazy_ptr" version of the symbol.
+; CHECK: LCPI0_0:
+; CHECK-NEXT: .long L_var$non_lazy_ptr-(LPC0_0+4)
+}
+
+define i32 @test_movw_movt() {
+; CHECK-LABEL: test_movw_movt:
+  %val = load i32* @var
+  ret i32 %val
+
+  ; movw/movt should also address their symbols MachO-style
+; CHECK: movw [[RTMP:r[0-9]+]], :lower16:(L_var$non_lazy_ptr-(LPC1_0+4))
+; CHECK: movt [[RTMP]], :upper16:(L_var$non_lazy_ptr-(LPC1_0+4))
+; CHECK: LPC1_0:
+; CHECK: add [[RTMP]], pc
+}
+
+declare void @llvm.trap()
+
+define void @test_trap() {
+; CHECK-LABEL: test_trap:
+
+  ; Bare-metal MachO gets compiled on top of normal MachO toolchain which
+  ; understands trap natively.
+  call void @llvm.trap()
+; CHECK: trap
+
+  ret void
+}
+
+define i32 @test_frame_ptr() {
+; CHECK-LABEL: test_frame_ptr:
+  call void @test_trap()
+
+  ; Frame pointer is r7 as for Darwin
+; CHECK: mov r7, sp
+  ret i32 42
+}
+
+%big_arr = type [8 x i32]
+define void @test_two_areas(%big_arr* %addr) {
+; CHECK-LABEL: test_two_areas:
+  %val = load %big_arr* %addr
+  call void @test_trap()
+  store %big_arr %val, %big_arr* %addr
+
+  ; This goes with the choice of r7 as FP (largely). FP and LR have to be stored
+  ; consecutively on the stack for the frame record to be valid, which means we
+  ; need the 2 register-save areas employed by iOS.
+; CHECK-NON-FAST: push {r4, r5, r6, r7, lr}
+; CHECK-NON-FAST: push.w {r8, r9, r10, r11}
+; ...
+; CHECK-NON-FAST: pop.w {r8, r9, r10, r11}
+; CHECK-NON-FAST: pop {r4, r5, r6, r7, pc}
+  ret void
+}
+
+define void @test_tail_call() {
+; CHECK-LABEL: test_tail_call:
+  tail call void @test_trap()
+
+  ; Tail calls should be available and use Thumb2 branch.
+; CHECK: b.w _test_trap
+  ret void
+}
+
+define float @test_softfloat_calls(float %in) {
+; CHECK-LABEL: test_softfloat_calls:
+  %sum = fadd float %in, %in
+
+  ; Soft-float calls should be GNU-style rather than RTABI and should not be the
+  ; *vfp variants used for ARMv6 iOS.
+; CHECK: blx ___addsf3{{$}}
+  ret float %sum
+}
+
+  ; Even bare-metal PIC needs GOT-like behaviour, in principle. Depends a bit on
+  ; the use-case of course, but LLVM doesn't know what that is.
+; CHECK: non_lazy_symbol_pointers
+; CHECK: L_var$non_lazy_ptr:
+; CHECK-NEXT:   .indirect_symbol _var
+
+  ; All MachO objects should have this to give the linker leeway in removing
+  ; dead code.
+; CHECK: .subsections_via_symbols