[llvm] d4257fb - [llvm-readobj] Improve printing of Windows ARM packed unwind info

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Wed May 18 11:37:05 PDT 2022


Author: Martin Storsjö
Date: 2022-05-18T21:33:08+03:00
New Revision: d4257fbbba234cdbb8d1973c508ee1aa1adcb4f2

URL: https://github.com/llvm/llvm-project/commit/d4257fbbba234cdbb8d1973c508ee1aa1adcb4f2
DIFF: https://github.com/llvm/llvm-project/commit/d4257fbbba234cdbb8d1973c508ee1aa1adcb4f2.diff

LOG: [llvm-readobj] Improve printing of Windows ARM packed unwind info

Fix a couple minor details in the existing logic for calculating
saved registers and stack adjustment.

Synthesize the corresponding prologues and epilogues and print them.
(This supersedes the previous printout of one single list of stored
registers; as there's lots of minor nuance differences in how
registers are pushed/popped in various corner cases, it's better to
print the full prologue/epilogue instead of trying to condense it
into one single list.)

Print the raw values of the fields Reg, R, L (LinkRegister) and C
(Chaining) instead of only printing the derived values.

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

Added: 
    llvm/test/tools/llvm-readobj/COFF/arm-unwind-packed.s

Modified: 
    llvm/include/llvm/Support/ARMWinEH.h
    llvm/lib/Support/ARMWinEH.cpp
    llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
    llvm/tools/llvm-readobj/ARMWinEHPrinter.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/ARMWinEH.h b/llvm/include/llvm/Support/ARMWinEH.h
index 327aa9804849f..dee2f31fb1275 100644
--- a/llvm/include/llvm/Support/ARMWinEH.h
+++ b/llvm/include/llvm/Support/ARMWinEH.h
@@ -199,13 +199,14 @@ inline bool EpilogueFolding(const RuntimeFunction &RF) {
 inline uint16_t StackAdjustment(const RuntimeFunction &RF) {
   uint16_t Adjustment = RF.StackAdjust();
   if (Adjustment >= 0x3f4)
-    return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0;
+    return (Adjustment & 0x3) + 1;
   return Adjustment;
 }
 
 /// SavedRegisterMask - Utility function to calculate the set of saved general
 /// purpose (r0-r15) and VFP (d0-d31) registers.
-std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF);
+std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF,
+                                                bool Prologue = true);
 
 /// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
 ///

diff  --git a/llvm/lib/Support/ARMWinEH.cpp b/llvm/lib/Support/ARMWinEH.cpp
index 8e7fa1149082f..29c7a28541f23 100644
--- a/llvm/lib/Support/ARMWinEH.cpp
+++ b/llvm/lib/Support/ARMWinEH.cpp
@@ -11,22 +11,35 @@
 namespace llvm {
 namespace ARM {
 namespace WinEH {
-std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF) {
+std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF,
+                                                bool Prologue) {
   uint8_t NumRegisters = RF.Reg();
   uint8_t RegistersVFP = RF.R();
   uint8_t LinkRegister = RF.L();
   uint8_t ChainedFrame = RF.C();
 
-  uint16_t GPRMask = (ChainedFrame << 11) | (LinkRegister << 14);
+  uint16_t GPRMask = (ChainedFrame << 11);
   uint32_t VFPMask = 0;
 
+  if (Prologue) {
+    GPRMask |= (LinkRegister << 14);
+  } else {
+    // If Ret != 0, we pop into Lr and return later
+    if (RF.Ret() != ReturnType::RT_POP)
+      GPRMask |= (LinkRegister << 14);
+    else if (!RF.H()) // If H == 0, we pop directly into Pc
+      GPRMask |= (LinkRegister << 15);
+    // else, Ret == 0 && H == 1, we pop into Pc separately afterwards
+  }
+
   if (RegistersVFP)
     VFPMask |= (((1 << ((NumRegisters + 1) % 8)) - 1) << 8);
   else
     GPRMask |= (((1 << (NumRegisters + 1)) - 1) << 4);
 
-  if (PrologueFolding(RF))
-    GPRMask |= (((1 << (NumRegisters + 1)) - 1) << (~RF.StackAdjust() & 0x3));
+  if ((PrologueFolding(RF) && Prologue) || (EpilogueFolding(RF) && !Prologue))
+    GPRMask |= (((1 << ((RF.StackAdjust() & 0x3) + 1)) - 1)
+                << (~RF.StackAdjust() & 0x3));
 
   return std::make_pair(GPRMask, VFPMask);
 }

diff  --git a/llvm/test/tools/llvm-readobj/COFF/arm-unwind-packed.s b/llvm/test/tools/llvm-readobj/COFF/arm-unwind-packed.s
new file mode 100644
index 0000000000000..385f33c81ea33
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/COFF/arm-unwind-packed.s
@@ -0,0 +1,735 @@
+// REQUIRES: arm-registered-target
+// RUN: llvm-mc -filetype=obj -triple thumbv7-windows-gnu %s -o %t.o
+// RUN: llvm-readobj --unwind %t.o | FileCheck --strict-whitespace %s
+
+// CHECK:       RuntimeFunction {
+// CHECK-NEXT:    Function: func6
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 8
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 0
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func7
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 8
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 0
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r4}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r4}
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func8
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 10
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 0
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r4, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r4, lr}
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func9
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 24
+// CHECK-NEXT:    ReturnType: b.w <target>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 32
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #32
+// CHECK-NEXT:      vpush {d8}
+// CHECK-NEXT:      push {lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #32
+// CHECK-NEXT:      vpop {d8}
+// CHECK-NEXT:      pop {lr}
+// CHECK-NEXT:      b.w <target>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func10
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 26
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 1
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #16
+// CHECK-NEXT:      vpush {d8-d9}
+// CHECK-NEXT:      mov r11, sp
+// CHECK-NEXT:      push {r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      vpop {d8-d9}
+// CHECK-NEXT:      pop {r11, lr}
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func11
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 24
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 1
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #16
+// CHECK-NEXT:      vpush {d8-d9}
+// CHECK-NEXT:      mov r11, sp
+// CHECK-NEXT:      push {r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      vpop {d8-d9}
+// CHECK-NEXT:      pop {r11, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func12
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 18
+// CHECK-NEXT:    ReturnType: b.w <target>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 6
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #16
+// CHECK-NEXT:      vpush {d8-d14}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      vpop {d8-d14}
+// CHECK-NEXT:      b.w <target>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func13
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 18
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 6
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 20
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #20
+// CHECK-NEXT:      add.w r11, sp, #28
+// CHECK-NEXT:      push {r4-r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #20
+// CHECK-NEXT:      pop {r4-r11, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func14
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 14
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 20
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #20
+// CHECK-NEXT:      push {r4-r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #20
+// CHECK-NEXT:      pop {r4-r11, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func15
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 20
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 512
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #512
+// CHECK-NEXT:      push {r4, lr}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #512
+// CHECK-NEXT:      pop {r4}
+// CHECK-NEXT:      ldr pc, [sp], #20
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func16
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 20
+// CHECK-NEXT:    ReturnType: b.w <target>
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 0
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      mov r11, sp
+// CHECK-NEXT:      push {r11, lr}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r11, lr}
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      b.w <target>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func17
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 20
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 512
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #512
+// CHECK-NEXT:      push {r4}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #512
+// CHECK-NEXT:      pop {r4}
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func18
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 6
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 4
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r3, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r3, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func19
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 12
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r0-r4}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r0-r4}
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func20
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 14
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r0-r4}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      pop {r4}
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func21
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 14
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #16
+// CHECK-NEXT:      push {r4}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r0-r4}
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func22
+// CHECK-NEXT:    Fragment: Yes
+// CHECK-NEXT:    FunctionLength: 14
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 512
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #512
+// CHECK-NEXT:      push {r4, lr}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #512
+// CHECK-NEXT:      pop {r4}
+// CHECK-NEXT:      ldr pc, [sp], #20
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func23
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 12
+// CHECK-NEXT:    ReturnType: (no epilogue)
+// CHECK-NEXT:    HomedParameters: Yes
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 512
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #512
+// CHECK-NEXT:      push {r4, lr}
+// CHECK-NEXT:      push {r0-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func24
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 16
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 3
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 8
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      add.w r11, sp, #24
+// CHECK-NEXT:      push {r2-r7, r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #8
+// CHECK-NEXT:      pop {r4-r7, r11, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func25
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 16
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 3
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: Yes
+// CHECK-NEXT:    StackAdjustment: 8
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #8
+// CHECK-NEXT:      add.w r11, sp, #16
+// CHECK-NEXT:      push {r4-r7, r11, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r2-r7, r11, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func26
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 8
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 12
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      push {r1-r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #12
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func27
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 8
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 7
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 12
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #12
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      pop {r1-r3}
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func28
+// CHECK-NEXT:    Fragment: No
+// CHECK-NEXT:    FunctionLength: 8
+// CHECK-NEXT:    ReturnType: bx <reg>
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 0
+// CHECK-NEXT:    R: 1
+// CHECK-NEXT:    LinkRegister: No
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 4
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      vpush {d8}
+// CHECK-NEXT:      push {r3}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      vpop {d8}
+// CHECK-NEXT:      pop {r3}
+// CHECK-NEXT:      bx <reg>
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+// CHECK-NEXT:  RuntimeFunction {
+// CHECK-NEXT:    Function: func29
+// CHECK-NEXT:    Fragment: Yes
+// CHECK-NEXT:    FunctionLength: 6
+// CHECK-NEXT:    ReturnType: pop {pc}
+// CHECK-NEXT:    HomedParameters: No
+// CHECK-NEXT:    Reg: 2
+// CHECK-NEXT:    R: 0
+// CHECK-NEXT:    LinkRegister: Yes
+// CHECK-NEXT:    Chaining: No
+// CHECK-NEXT:    StackAdjustment: 16
+// CHECK-NEXT:    Prologue [
+// CHECK-NEXT:      sub sp, sp, #16
+// CHECK-NEXT:      push {r4-r6, lr}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:    Epilogue [
+// CHECK-NEXT:      add sp, sp, #16
+// CHECK-NEXT:      pop {r4-r6, pc}
+// CHECK-NEXT:    ]
+// CHECK-NEXT:  }
+
+        .thumb
+        .syntax unified
+
+func6:
+        nop
+        nop
+        nop
+        bx lr
+
+func7:
+        push {r4}
+        nop
+        pop {r4}
+        bx lr
+
+func8:
+        push {r4,lr}
+        nop
+        pop {r4,lr}
+        bx lr
+
+func9:
+        push {lr}
+        vpush {d8}
+        sub sp, sp, #32
+        nop
+        add sp, sp, #32
+        vpop {d8}
+        pop {lr}
+        b tailcall
+
+func10:
+        push {r11,lr}
+        mov r11, sp
+        vpush {d8-d9}
+        sub sp, sp, #16
+        nop
+        add sp, sp, #16
+        vpop {d8-d9}
+        pop {r11,lr}
+        bx lr
+
+func11:
+        push {r11,lr}
+        mov r11, sp
+        vpush {d8-d9}
+        sub sp, sp, #16
+        nop
+        add sp, sp, #16
+        vpop {d8-d9}
+        pop {r11,pc}
+
+func12:
+        vpush {d8-d14}
+        sub sp, sp, #16
+        nop
+        add sp, sp, #16
+        vpop {d8-d14}
+        b tailcall
+
+func13:
+        push {r4-r11,lr}
+        add r11, sp, #0x1c
+        sub sp, sp, #20
+        nop
+        add sp, sp, #20
+        pop {r4-r11,pc}
+
+func14:
+        push {r4-r11,lr}
+        sub sp, sp, #20
+        nop
+        add sp, sp, #20
+        pop {r4-r11,pc}
+
+func15:
+        push {r0-r3}
+        push {r4,lr}
+        sub sp, sp, #512
+        nop
+        add sp, sp, #512
+        pop {r4}
+        ldr pc, [sp], #20
+
+func16:
+        push {r0-r3}
+        push {r11,lr}
+        mov r11, sp
+        nop
+        pop {r11, lr}
+        add sp, sp, #16
+        b tailcall
+
+func17:
+        push {r0-r3}
+        push {r4}
+        sub sp, sp, #512
+        nop
+        add sp, sp, #512
+        pop {r4}
+        add sp, sp, #16
+        bx lr
+
+func18:
+        push {r3,lr}
+        nop
+        pop {r3,pc}
+
+func19:
+        push {r0-r3}
+        push {r0-r4}
+        nop
+        pop {r0-r4}
+        add sp, sp, #16
+        bx lr
+
+func20:
+        push {r0-r3}
+        push {r0-r4}
+        nop
+        add sp, sp, #16
+        pop {r4}
+        add sp, sp, #16
+        bx lr
+
+func21:
+        push {r0-r3}
+        push {r4}
+        sub sp, sp, #16
+        nop
+        pop {r0-r4}
+        add sp, sp, #16
+        bx lr
+
+func22:
+        nop
+        nop
+        add sp, sp, #512
+        pop {r4}
+        ldr pc, [sp], #20
+
+func23:
+        push {r0-r3}
+        push {r4,lr}
+        sub sp, sp, #512
+        nop
+        nop
+
+func24:
+        push {r2-r7,r11,lr}
+        add r11, sp, #24
+        nop
+        add sp, sp, #8
+        pop {r4-r7,r11,pc}
+
+func25:
+        push {r4-r7,r11,lr}
+        add r11, sp, #16
+        sub sp, sp, #8
+        nop
+        pop {r2-r7,r11,pc}
+
+func26:
+        push {r1-r3}
+        nop
+        add sp, sp, #12
+        bx lr
+
+func27:
+        sub sp, sp, #12
+        nop
+        pop {r1-r3}
+        bx lr
+
+func28:
+        push {r3}
+        vpush {d8}
+        nop
+        vpop {d8}
+        pop {r3}
+        bx lr
+
+func29:
+        nop
+        pop {r4-r11,pc}
+
+        .section .pdata,"dr"
+        .rva func6
+        .long 0x000f2011
+        .rva func7
+        .long 0x00002011
+        .rva func8
+        .long 0x00102015
+        .rva func9
+        .long 0x02184031
+        .rva func10
+        .long 0x01392035
+        .rva func11
+        .long 0x01390031
+        .rva func12
+        .long 0x010e4025
+        .rva func13
+        .long 0x01760025
+        .rva func14
+        .long 0x0157001d
+        .rva func15
+        .long 0x20108029
+        .rva func16
+        .long 0x003fc029
+        .rva func17
+        .long 0x2000a029
+        .rva func18
+        .long 0xff1f000d
+        .rva func19
+        .long 0xffc0a019
+        .rva func20
+        .long 0xfdc0a01d
+        .rva func21
+        .long 0xfec0a01d
+        .rva func22
+        .long 0x2010801e
+        .rva func23
+        .long 0x2010e019
+        .rva func24
+        .long 0xfd730021
+        .rva func25
+        .long 0xfe730021
+        .rva func26
+        .long 0xfd8f2011
+        .rva func27
+        .long 0xfe8f2011
+        .rva func28
+        .long 0xff082011
+        .rva func29
+        .long 0x0112000e

diff  --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 201cdced8667b..b7cbf353c43f1 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -200,15 +200,10 @@ static void printRange(raw_ostream &OS, uint32_t Mask, ListSeparator &LS,
     printRange(OS, LS, First, End, Letter);
 }
 
-void Decoder::printRegisters(
-    const std::pair<uint16_t, uint32_t> &RegisterMask) {
-  const uint16_t GPRMask = std::get<0>(RegisterMask);
-  const uint32_t VFPMask = std::get<1>(RegisterMask);
-
+void Decoder::printGPRMask(uint16_t GPRMask) {
   OS << '{';
   ListSeparator LS;
   printRange(OS, GPRMask, LS, 0, 12, 'r');
-  printRange(OS, VFPMask, LS, 0, 31, 'd');
   if (GPRMask & (1 << 14))
     OS << LS << "lr";
   if (GPRMask & (1 << 15))
@@ -216,6 +211,13 @@ void Decoder::printRegisters(
   OS << '}';
 }
 
+void Decoder::printVFPMask(uint32_t VFPMask) {
+  OS << '{';
+  ListSeparator LS;
+  printRange(OS, VFPMask, LS, 0, 31, 'd');
+  OS << '}';
+}
+
 ErrorOr<object::SectionRef>
 Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
   for (const auto &Section : COFF.sections()) {
@@ -344,7 +346,7 @@ bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,
   SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
                            OC[Offset + 0], OC[Offset + 1],
                            Prologue ? "push" : "pop");
-  printRegisters(std::make_pair(RegisterMask, 0));
+  printGPRMask(RegisterMask);
   OS << '\n';
 
   Offset += 2;
@@ -373,7 +375,7 @@ bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
                            Prologue ? "push" : "pop");
-  printRegisters(std::make_pair(GPRMask, 0));
+  printGPRMask(GPRMask);
   OS << '\n';
 
   ++Offset;
@@ -390,7 +392,7 @@ bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
                            Prologue ? "push" : "pop");
-  printRegisters(std::make_pair(GPRMask, 0));
+  printGPRMask(GPRMask);
   OS << '\n';
 
   ++Offset;
@@ -404,7 +406,7 @@ bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
                            Prologue ? "vpush" : "vpop");
-  printRegisters(std::make_pair(0, VFPMask));
+  printVFPMask(VFPMask);
   OS << '\n';
 
   ++Offset;
@@ -431,7 +433,7 @@ bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
                            OC[Offset + 1], Prologue ? "push" : "pop");
-  printRegisters(std::make_pair(GPRMask, 0));
+  printGPRMask(GPRMask);
   OS << '\n';
 
   Offset += 2;
@@ -480,7 +482,7 @@ bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
-  printRegisters(std::make_pair(0, VFPMask));
+  printVFPMask(VFPMask);
   OS << '\n';
 
   Offset += 2;
@@ -495,7 +497,7 @@ bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,
 
   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
-  printRegisters(std::make_pair(0, VFPMask));
+  printVFPMask(VFPMask);
   OS << '\n';
 
   Offset += 2;
@@ -1132,17 +1134,75 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
 
   SW.printString("Function",
                  formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
-  if (!isAArch64)
-    SW.printBoolean("Fragment",
-                    RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
+  SW.printBoolean("Fragment",
+                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
   SW.printNumber("FunctionLength", RF.FunctionLength());
   SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
   SW.printBoolean("HomedParameters", RF.H());
-  SW.startLine() << "SavedRegisters: ";
-                 printRegisters(SavedRegisterMask(RF));
-  OS << '\n';
+  SW.printNumber("Reg", RF.Reg());
+  SW.printNumber("R", RF.R());
+  SW.printBoolean("LinkRegister", RF.L());
+  SW.printBoolean("Chaining", RF.C());
   SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
 
+  {
+    ListScope PS(SW, "Prologue");
+
+    uint16_t GPRMask, VFPMask;
+    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/true);
+
+    if (StackAdjustment(RF) && !PrologueFolding(RF))
+      SW.startLine() << "sub sp, sp, #" << StackAdjustment(RF) * 4 << "\n";
+    if (VFPMask) {
+      SW.startLine() << "vpush ";
+      printVFPMask(VFPMask);
+      OS << "\n";
+    }
+    if (RF.C()) {
+      // Count the number of registers pushed below R11
+      int FpOffset = 4 * countPopulation(GPRMask & ((1U << 11) - 1));
+      if (FpOffset)
+        SW.startLine() << "add.w r11, sp, #" << FpOffset << "\n";
+      else
+        SW.startLine() << "mov r11, sp\n";
+    }
+    if (GPRMask) {
+      SW.startLine() << "push ";
+      printGPRMask(GPRMask);
+      OS << "\n";
+    }
+    if (RF.H())
+      SW.startLine() << "push {r0-r3}\n";
+  }
+
+  if (RF.Ret() != ReturnType::RT_NoEpilogue) {
+    ListScope PS(SW, "Epilogue");
+
+    uint16_t GPRMask, VFPMask;
+    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/false);
+
+    if (StackAdjustment(RF) && !EpilogueFolding(RF))
+      SW.startLine() << "add sp, sp, #" << StackAdjustment(RF) * 4 << "\n";
+    if (VFPMask) {
+      SW.startLine() << "vpop ";
+      printVFPMask(VFPMask);
+      OS << "\n";
+    }
+    if (GPRMask) {
+      SW.startLine() << "pop ";
+      printGPRMask(GPRMask);
+      OS << "\n";
+    }
+    if (RF.H()) {
+      if (RF.L() == 0 || RF.Ret() != ReturnType::RT_POP)
+        SW.startLine() << "add sp, sp, #16\n";
+      else
+        SW.startLine() << "ldr pc, [sp], #20\n";
+    }
+    if (RF.Ret() != ReturnType::RT_POP)
+      SW.startLine() << RF.Ret() << '\n';
+  }
+
   return true;
 }
 

diff  --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index 920d4e5f73325..ceaa866ff2150 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -133,7 +133,8 @@ class Decoder {
   void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
                      bool Prologue);
 
-  void printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask);
+  void printGPRMask(uint16_t Mask);
+  void printVFPMask(uint32_t Mask);
 
   ErrorOr<object::SectionRef>
   getSectionContaining(const object::COFFObjectFile &COFF, uint64_t Address);


        


More information about the llvm-commits mailing list