[LLVMdev] spilling & restoring registers for EHReturn & return _Unwind_Reason_Code

Robert Lytton robert at xmos.com
Fri Dec 20 09:33:36 PST 2013


Hi

I'm working on the XCore target and am having difficulty building libgcc.

Background:
If I use a libgcc built by llvm3.0-gcc with my current clang-llvm3.3 compiler, exceptions 'seem' to work.
Trying to rebuild libgcc however breaks exception handling - they aren't caught!
I thus assumed I needed to focus on the unwind code and particularly functions that call @llvm.eh.unwind.init().
I reinforced this assumption by swapping the assembler output from the llvm-gcc lib into my new lib for some such functions - and exceptions 'seem' to work again.
(the critical functions being found in eh_personality.o, unwind-dw2.o, eh_throw.o)

Looking at functions built using the llvm3.0-gcc front end, I noticed that R0 & R1 were spilled/restored (clobbering '_Unwind_Reason_Code') , along with the callee saved regs.

So how are things meant to work?

For example take:
    define i32 @_Unwind_RaiseException(%struct._Unwind_Exception* %exc)

This calls:
    @llvm.eh.unwind.init()
followed by:
    call void @llvm.eh.return()
    ret i32 '_Unwind_Reason_Code'
    call void @abort()

>From my reading, I need to spill all callee save regs (R4-R10) during the prologue.
(R0-R3, LR & FP are caller saved/argument registers)
BUT
Q: what about exception info (and what is this)?
Q: is it %exc (R0)?
Q: is it 'ExceptionPointerRegister' & 'ExceptionSelectorRegister' (R0&R1)?

Then:

Calling abort, does not restore callee save regs.

For 'return' epilogues, I restore callee save regs (R4-10) & R0 will hold the '_Unwind_Reason_Code'.

However, what must I do for llvm.eh.return() epilogues?
Q: do I restore callee save regs (R4-R10)?
Q: do I restore exception info (R0-R1)?


I have tried only spilling/restoring callee save regs - but this doesn't work, I end up with an uncaught exception.

So I tried spilling R0 & R1 and trying to restore them only for llvm.eh.return() but this will not compile.
viz unwind-dw2.c will report:
    BB#0: derived from LLVM BB %entry
        Live Ins: %R0 %R0 %R1 %R4 %R5 %R6 %R7 %R8 %R9 %R10 %LR %R0 %R1
        ENTSP_lu6 120, %SP<imp-def>, %SP<imp-use>, %LR<imp-use,kill>
        PROLOG_LABEL <MCSym=.Ltmp68>
        PROLOG_LABEL <MCSym=.Ltmp69>
        STWSP_lru6 %R0<kill>, 119, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp59>
        STWSP_lru6 %R1<kill>, 118, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp60>
        STWSP_lru6 %R4<kill>, 117, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp61>
        STWSP_lru6 %R5<kill>, 116, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp62>
        STWSP_lru6 %R6<kill>, 115, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp63>
        STWSP_lru6 %R7<kill>, 114, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp64>
        STWSP_lru6 %R8<kill>, 113, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp65>
        STWSP_lru6 %R9<kill>, 112, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp66>
        STWSP_lru6 %R10<kill>, 111, %SP<imp-use>
        PROLOG_LABEL <MCSym=.Ltmp67>
        %R4<def> = COPY %R0
...
    *** Bad machine code: Using an undefined physical register ***
    - function:    _Unwind_RaiseException
    - basic block: BB#0 entry (0x33d9f20)
    - instruction: %R4<def> = COPY %R0
    - operand 1:   %R0


To see if I am on the right track I may try to:
    1. hack llvm to not kill R0 during the spill
    2. manually add spilled/restore R0 & R1 into the assembler output for functions that call llvm.eh.return().
However, I would prefer knowledgeable input at this stage!

Thank you.

Robert


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20131220/720e074d/attachment.html>


More information about the llvm-dev mailing list