[PATCH] Segmented stack support ARM iOS

Valerii Hiora valerii.hiora at gmail.com
Wed Apr 23 11:32:35 PDT 2014


Patch enables support of segmented stacks on armv7 iOS. 

Although it seems to work fine, it relies on a couple of assumptions made about iOS internals which could be wrong so input from Apple engineers is really important.

To be precise, it uses Apple-specific implementation of _pthread_{get,set}specific_direct taken from http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h and uses static key #149.  While it is not in Apple-reserved range (0..119 as of libc 825.40.1), it still unclear if it is smaller than total count of reserved slots.

http://reviews.llvm.org/D3473

Files:
  lib/Target/ARM/ARMFrameLowering.cpp

Index: lib/Target/ARM/ARMFrameLowering.cpp
===================================================================
--- lib/Target/ARM/ARMFrameLowering.cpp
+++ lib/Target/ARM/ARMFrameLowering.cpp
@@ -1671,13 +1671,13 @@
   bool Thumb = ST->isThumb();
 
   // Sadly, this currently doesn't support varargs, platforms other than
-  // android/linux. Note that thumb1/thumb2 are support for android/linux.
-  if (MF.getFunction()->isVarArg())
-    report_fatal_error("Segmented stacks do not support vararg functions.");
-  if (!ST->isTargetAndroid() && !ST->isTargetLinux())
-    report_fatal_error("Segmented stacks not supported on this platform.");
-
-  MachineBasicBlock &prologueMBB = MF.front();
+  // android/linux. Note that thumb1/thumb2 are support for android/linux.
+  if (MF.getFunction()->isVarArg())
+    report_fatal_error("Segmented stacks do not support vararg functions.");
+  if (!ST->isTargetAndroid() && !ST->isTargetLinux() && !ST->isTargetIOS())
+    report_fatal_error("Segmented stacks not supported on this platform.");
+
+  MachineBasicBlock &prologueMBB = MF.front();
   MachineFrameInfo *MFI = MF.getFrameInfo();
   MachineModuleInfo &MMI = MF.getMMI();
   MCContext &Context = MMI.getContext();
@@ -1795,16 +1795,45 @@
                      .addImm(15)
                      .addImm(0)
                      .addImm(13)
-                     .addImm(0)
-                     .addImm(3));
-
-    // Use the last tls slot on android and a private field of the TCP on linux.
-    assert(ST->isTargetAndroid() || ST->isTargetLinux());
-    unsigned TlsOffset = ST->isTargetAndroid() ? 63 : 1;
-
-    // Get the stack limit from the right offset
-    // ldr SR0, [sr0, #4 * TlsOffset]
-    AddDefaultPred(BuildMI(GetMBB, DL, TII.get(ARM::LDRi12), ScratchReg0)
+                     .addImm(0)
+                     .addImm(3));
+
+    unsigned TlsOffset = 0;
+    if (ST->isTargetAndroid() || ST->isTargetLinux()) {
+      // Use the last tls slot on android and a private field of the TCP on linux.
+      TlsOffset = ST->isTargetAndroid() ? 63 : 1;
+    } else if (ST->isTargetIOS()) {
+      // Idea for iOS was taken from 
+      // http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
+      //
+      // In short: _pthread_{get,set}_specific_direct allows extremely fast 
+      // access, exactly what is required for segmented stack 
+      // There is a pool of reserved slots for Apple internal use (0..119)
+      // First dynamic allocated pthread key starts with 257 (on iOS7)
+      // So using slot 149 should be pretty safe ASSUMING space is reserved 
+      // for every key < first dynamic key
+      // But it's just assumption...
+      //
+      // There is also an opportunity to steal keys reserved for Garbage Collection
+      // ranges 80..89 and 110..119, especially considering the fact Garbage Collection
+      // never supposed to work on iOS. But as everybody knows it - there is a chance 
+      // that those slots will be re-used, like it happened with key 95 (moved from 
+      // JavaScriptCore to CoreText)
+      //
+      // It will be great if slot for segmented stack will be officially reserved 
+      // by Apple to avoid any clashes or misuse by other compilers. 
+      // Good example is the key for SJ/LJ exceptions
+
+      // Bic SR0, SR0, #3
+      AddDefaultCC(AddDefaultPred(BuildMI(GetMBB, DL, TII.get(ARM::BICri), ScratchReg0)
+                                    .addReg(ScratchReg0, RegState::Kill)
+                                    .addImm(3)));
+      TlsOffset = 149;      
+    } 
+
+    // Get the stack limit from the right offset
+    // ldr SR0, [sr0, #4 * TlsOffset]
+    AddDefaultPred(BuildMI(GetMBB, DL, TII.get(ARM::LDRi12), ScratchReg0)
                       .addReg(ScratchReg0).addImm(4 * TlsOffset));
   }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3473.8779.patch
Type: text/x-patch
Size: 3885 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140423/b235e0fd/attachment.bin>


More information about the llvm-commits mailing list