Generate ARM CFIs in prolog (#21505)
authorAndrey Kvochko <kvochko@users.noreply.github.com>
Tue, 18 Dec 2018 05:28:32 +0000 (08:28 +0300)
committerJan Kotas <jkotas@microsoft.com>
Tue, 18 Dec 2018 05:28:32 +0000 (21:28 -0800)
src/jit/compiler.h
src/jit/unwind.cpp
src/jit/unwindarm.cpp

index 7b91d39..8a8a328 100644 (file)
@@ -7487,10 +7487,6 @@ private:
                      DWORD                 cfiCodeBytes,
                      const CFI_CODE* const pCfiCode);
 #endif
-#if defined(_TARGET_ARM_)
-    bool unwindCfiEpilogFormed; // Avoid duplicated unwind info for methods with multiple epilogs (we expect and require
-                                // all the epilogs to be precisely the same)
-#endif
 
 #endif // _TARGET_UNIX_
 
index f27a847..0729648 100644 (file)
@@ -122,56 +122,39 @@ void Compiler::unwindGetFuncLocations(FuncInfoDsc*             func,
 
 void Compiler::createCfiCode(FuncInfoDsc* func, UCHAR codeOffset, UCHAR cfiOpcode, USHORT dwarfReg, INT offset)
 {
-#if defined(_TARGET_ARM_)
-    if (compGeneratingEpilog && unwindCfiEpilogFormed)
-        return;
-#endif
     CFI_CODE cfiEntry(codeOffset, cfiOpcode, dwarfReg, offset);
     func->cfiCodes->push_back(cfiEntry);
 }
 
 void Compiler::unwindPushPopCFI(regNumber reg)
 {
-#if defined(_TARGET_ARM_)
-    assert(compGeneratingEpilog);
-#else
     assert(compGeneratingProlog);
-#endif
 
     FuncInfoDsc* func     = funCurrentFunc();
-    unsigned int cbProlog = 0;
-    if (compGeneratingProlog)
-    {
-        cbProlog = unwindGetCurrentOffset(func);
-        noway_assert((BYTE)cbProlog == cbProlog);
-
-        createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, REGSIZE_BYTES == 8 ? 8 : 4);
-    }
-
-    if ((RBM_CALLEE_SAVED & genRegMask(reg))
-#if defined(UNIX_AMD64_ABI)
-#if ETW_EBP_FRAMED
-        // In case of ETW_EBP_FRAMED defined the REG_FPBASE (RBP)
-        // is excluded from the callee-save register list.
-        // Make sure the register gets PUSH unwind info in this case,
-        // since it is pushed as a frame register.
-        || (reg == REG_FPBASE)
-#endif // ETW_EBP_FRAMED
-#endif // UNIX_AMD64_ABI
+    unsigned int cbProlog = unwindGetCurrentOffset(func);
+    noway_assert((BYTE)cbProlog == cbProlog);
+
+    regMaskTP relOffsetMask = RBM_CALLEE_SAVED
+#if defined(UNIX_AMD64_ABI) && ETW_EBP_FRAMED
+                              // In case of ETW_EBP_FRAMED defined the REG_FPBASE (RBP)
+                              // is excluded from the callee-save register list.
+                              // Make sure the register gets PUSH unwind info in this case,
+                              // since it is pushed as a frame register.
+                              | RBM_FPBASE
+#endif
 #if defined(_TARGET_ARM_)
-        || (reg == REG_R11) || (reg == REG_LR) || (reg == REG_PC)
-#endif // _TARGET_ARM_
-            )
+                              | RBM_R11 | RBM_LR | RBM_PC
+#endif
+        ;
+
+    if (relOffsetMask & genRegMask(reg))
     {
         createCfiCode(func, cbProlog, CFI_REL_OFFSET, mapRegNumToDwarfReg(reg));
     }
-#if defined(_TARGET_ARM_)
-    // The non-callee-saved registers are for stack space allocation only
     else
     {
         createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, REGSIZE_BYTES);
     }
-#endif // _TARGET_ARM_
 }
 
 typedef jitstd::vector<CFI_CODE> CFICodeVector;
@@ -218,11 +201,7 @@ void Compiler::unwindPushPopMaskCFI(regMaskTP regMask, bool isFloat)
 
 void Compiler::unwindAllocStackCFI(unsigned size)
 {
-#if defined(_TARGET_ARM_)
-    assert(compGeneratingEpilog);
-#else
     assert(compGeneratingProlog);
-#endif
     FuncInfoDsc* func     = funCurrentFunc();
     unsigned int cbProlog = 0;
     if (compGeneratingProlog)
@@ -242,18 +221,10 @@ void Compiler::unwindAllocStackCFI(unsigned size)
 //
 void Compiler::unwindSetFrameRegCFI(regNumber reg, unsigned offset)
 {
-#if defined(_TARGET_ARM_)
-    assert(compGeneratingEpilog);
-#else
     assert(compGeneratingProlog);
-#endif
     FuncInfoDsc* func     = funCurrentFunc();
-    unsigned int cbProlog = 0;
-    if (compGeneratingProlog)
-    {
-        cbProlog = unwindGetCurrentOffset(func);
-        noway_assert((BYTE)cbProlog == cbProlog);
-    }
+    unsigned int cbProlog = unwindGetCurrentOffset(func);
+    noway_assert((BYTE)cbProlog == cbProlog);
 
     createCfiCode(func, cbProlog, CFI_DEF_CFA_REGISTER, mapRegNumToDwarfReg(reg));
     if (offset != 0)
index cfd7290..4a2b838 100644 (file)
@@ -194,9 +194,6 @@ void Compiler::unwindBegProlog()
     if (generateCFIUnwindCodes())
     {
         unwindBegPrologCFI();
-#if defined(_TARGET_ARM_)
-        unwindCfiEpilogFormed = false;
-#endif
         return;
     }
 #endif // _TARGET_UNIX_
@@ -238,11 +235,6 @@ void Compiler::unwindBegEpilog()
 void Compiler::unwindEndEpilog()
 {
     assert(compGeneratingEpilog);
-#if defined(_TARGET_UNIX_)
-#if defined(_TARGET_ARM_)
-    unwindCfiEpilogFormed = true;
-#endif
-#endif // _TARGET_UNIX_
 }
 
 #if defined(_TARGET_ARM_)
@@ -379,6 +371,12 @@ void Compiler::unwindPushMaskInt(regMaskTP maskInt)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
+        // If we are pushing LR, we should give unwind codes in terms of caller's PC
+        if (maskInt & RBM_LR)
+        {
+            maskInt = (maskInt & ~RBM_LR) | RBM_PC;
+        }
+        unwindPushPopMaskCFI(maskInt, false);
         return;
     }
 #endif // _TARGET_UNIX_
@@ -395,6 +393,7 @@ void Compiler::unwindPushMaskFloat(regMaskTP maskFloat)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
+        unwindPushPopMaskCFI(maskFloat, true);
         return;
     }
 #endif // _TARGET_UNIX_
@@ -407,7 +406,6 @@ void Compiler::unwindPopMaskInt(regMaskTP maskInt)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
-        unwindPushPopMaskCFI(maskInt, false);
         return;
     }
 #endif // _TARGET_UNIX_
@@ -436,7 +434,6 @@ void Compiler::unwindPopMaskFloat(regMaskTP maskFloat)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
-        unwindPushPopMaskCFI(maskFloat, true);
         return;
     }
 #endif // _TARGET_UNIX_
@@ -451,7 +448,7 @@ void Compiler::unwindAllocStack(unsigned size)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
-        if (compGeneratingEpilog)
+        if (compGeneratingProlog)
         {
             unwindAllocStackCFI(size);
         }
@@ -505,7 +502,7 @@ void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset)
 #if defined(_TARGET_UNIX_)
     if (generateCFIUnwindCodes())
     {
-        if (compGeneratingEpilog)
+        if (compGeneratingProlog)
         {
             unwindSetFrameRegCFI(reg, offset);
         }