[Sparc] builtin setjmp / longjmp - need help to get past last problem

Hi,

I’m implementing __builtin_setjmp and __builtin_longjmp for Sparc 32 bit processors (64 bit later, time allowing).

I’m basing the code on the PowerPC version, which itself is based on the X86 version.

This code is very nearly working, and I’ve had it working for -O0 optimisation (with a slightly different version to that below), so I know it’s close.

However, the PowerPC code uses a trick to ensure that optimisations retain the jump targets required, using a Pseudo instruction “EH_SjLj_Setup” that expands simply to an IR comment, but makes the compiler think it needs to preserve the jump target address - which it does, to ensure that the jump target remains valid after any optimisations. Some of the comments at this URL relating to the PowerPC version help with understanding this: http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html[http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html](http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html)

However, when compiling for Sparc, I get a “Not supported instr” for the instruction EH_SjLj_Setup. Of course, it doesn’t exist in reality, but neither does it for PowerPC, so I can’t understand why there’s a difference between how it’s handled for the two targets.

I’ve included a full diff for the setjmp/longjmp change I’m making, but you’ll find the most pertinent lines if you search for the text “EH_SjLj_Setup”. You’ll find very similar code in the PowerPC backend.

If anyone spots any other mistakes or has comments, I’d be glad to know about them at this stage too. Note: I’ll comment as best I can how this works within the code when I get it working.

Index: SparcISelLowering.cpp

Chris.Dewhurst via llvm-dev <llvm-dev <at> lists.llvm.org> writes:

However, when compiling for Sparc, I get a "Not supported instr" for

the instruction EH_SjLj_Setup. Of course, it doesn't exist in reality,
but neither does it for PowerPC, so I can't understand why there's a
difference between how it's handled for the

two targets.

(Having found the answer to my own question, in case it helps others at
any time)

The difference is that the PowerPC version specifies "isCodeGenOnly = 1"
for *all* it's Pseudo instructions. For the Sparc version, you need to
specify this just for EH_SjLj_Setup instruction to avoid it being
optimised-away by the tablegen compiler.

Chris Dewhurst via llvm-dev <llvm-dev <at> lists.llvm.org> writes:

Chris.Dewhurst via llvm-dev <llvm-dev <at> lists.llvm.org> writes:

>
> However, when compiling for Sparc, I get a "Not supported instr" for
the instruction EH_SjLj_Setup. Of course, it doesn't exist in reality,
but neither does it for PowerPC, so I can't understand why there's a
difference between how it's handled for the
> two targets.

(Having found the answer to my own question, in case it helps others

at

any time)

The difference is that the PowerPC version specifies "isCodeGenOnly =

1"

for *all* it's Pseudo instructions. For the Sparc version, you need to
specify this just for EH_SjLj_Setup instruction to avoid it being
optimised-away by the tablegen compiler.

Sorry: I found that my test was giving me a false-positive on this. It's
nearly correct though.

In addition to isCodeGenOnly, you need to *not* have the isPseudo flag
set for the instruction. The PowerPC code is somewhat contradictory in
this in that the instruction is marked as being type "Pseudo", but for
PPC, this actually doesn't set the "isPseudo = 1" flag.

The best way to resolve this for Sparc is to simply use the InstSP
tablegen class instead, in a construct similar to this:

let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in {
  def EH_SjLj_Setup : InstSP<(outs), (ins brtarget:$ptr),
                        "#EH_SjLj_Setup\t$ptr", >,
                        Requires<[Is32Bit]>;
}