[all-commits] [llvm/llvm-project] d8e67c: [ARM] Add SEH opcodes in frame lowering

Martin Storsjö via All-commits all-commits at lists.llvm.org
Thu Jun 2 02:30:03 PDT 2022


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: d8e67c1cccd8fcb62230166caea744592288da17
      https://github.com/llvm/llvm-project/commit/d8e67c1cccd8fcb62230166caea744592288da17
  Author: Martin Storsjö <martin at martin.st>
  Date:   2022-06-02 (Thu, 02 Jun 2022)

  Changed paths:
    M llvm/lib/Target/ARM/ARMAsmPrinter.cpp
    M llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
    M llvm/lib/Target/ARM/ARMBaseInstrInfo.h
    M llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
    M llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
    M llvm/lib/Target/ARM/ARMFrameLowering.cpp
    M llvm/lib/Target/ARM/ARMInstrInfo.td
    M llvm/lib/Target/ARM/ARMInstrThumb2.td
    M llvm/lib/Target/ARM/Thumb2SizeReduction.cpp
    M llvm/test/CodeGen/ARM/Windows/dllimport.ll
    A llvm/test/CodeGen/ARM/Windows/wineh-opcodes.ll
    A llvm/test/CodeGen/ARM/Windows/wineh-tailmerge.ll
    M llvm/test/DebugInfo/COFF/ARMNT/arm-register-variables.ll

  Log Message:
  -----------
  [ARM] Add SEH opcodes in frame lowering

Skip inserting regular CFI instructions if using WinCFI.

This is based a fair amount on the corresponding ARM64 implementation,
but instead of trying to insert the SEH opcodes one by one where
we generate other prolog/epilog instructions, we try to walk over the
whole prolog/epilog range and insert them. This is done because in
many cases, the exact number of instructions inserted is abstracted
away deeper.

For some cases, we manually insert specific SEH opcodes directly where
instructions are generated, where the automatic mapping of instructions
to SEH opcodes doesn't hold up (e.g. for __chkstk stack probes).

Skip Thumb2SizeReduction for SEH prologs/epilogs, and force
tail calls to wide instructions (just like on MachO), to make sure
that the unwind info actually matches the width of the final
instructions, without heuristics about what later passes will do.

Mark SEH instructions as scheduling boundaries, to make sure that they
aren't reordered away from the instruction they describe by
PostRAScheduler.

Mark the SEH instructions with the NoMerge flag, to avoid doing
tail merging of functions that have multiple epilogs that all end
with the same sequence of "b <other>; .seh_nop_w, .seh_endepilogue".

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


  Commit: 2ab19bfa4125d803c16e60b5df4df9d03838e0ea
      https://github.com/llvm/llvm-project/commit/2ab19bfa4125d803c16e60b5df4df9d03838e0ea
  Author: Martin Storsjö <martin at martin.st>
  Date:   2022-06-02 (Thu, 02 Jun 2022)

  Changed paths:
    M llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    M llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
    M llvm/lib/Target/ARM/ARMCallingConv.td
    M llvm/lib/Target/ARM/ARMFrameLowering.cpp
    M llvm/lib/Target/ARM/ARMSubtarget.cpp
    M llvm/lib/Target/ARM/ARMSubtarget.h
    A llvm/test/CodeGen/ARM/Windows/wineh-framepointer.ll

  Log Message:
  -----------
  [ARM] Adjust the frame pointer when it's needed for SEH unwinding

For functions that require restoring SP from FP (e.g. that need to
align the stack, or that have variable sized allocations), the prologue
and epilogue previously used to look like this:

    push {r4-r5, r11, lr}
    add r11, sp, #8
    ...
    sub r4, r11, #8
    mov sp, r4
    pop {r4-r5, r11, pc}

This is problematic, because this unwinding operation (restoring sp
from r11 - offset) can't be expressed with the SEH unwind opcodes
(probably because this unwind procedure doesn't map exactly to
individual instructions; note the detour via r4 in the epilogue too).

To make unwinding work, the GPR push is split into two; the first one
pushing all other registers, and the second one pushing r11+lr, so that
r11 can be set pointing at this spot on the stack:

    push {r4-r5}
    push {r11, lr}
    mov r11, sp
    ...
    mov sp, r11
    pop {r11, lr}
    pop {r4-r5}
    bx lr

For the same setup, MSVC generates code that uses two registers;
r11 still pointing at the {r11,lr} pair, but a separate register
used for restoring the stack at the end:

    push {r4-r5, r7, r11, lr}
    add r11, sp, #12
    mov r7, sp
    ...
    mov sp, r7
    pop {r4-r5, r7, r11, pc}

For cases with clobbered float/vector registers, they are pushed
after the GPRs, before the {r11,lr} pair.

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


Compare: https://github.com/llvm/llvm-project/compare/5482ae632895...2ab19bfa4125


More information about the All-commits mailing list