On 08/20/2016 09:53 AM, Jeff Law wrote:
On 08/20/2016 06:01 AM, Daniel Santos wrote:
I have been unable to figure out how to (correctly) generate RTL (in
expand the pro/epilogue pass) to jump to a stub defined in libgcc for
the out-of-lined epilogue. If I write it as a function call, but then
set the insn's jump field to true it emits the correct jump asm, but
then it thinks it's a sibling call epilogue and it screws up other
things (just read up on the sibling call optimization earlier).

Basically, it should replace the function's ret with a jmp to the
outlined epilogue that will do the ret. Any pointers greatly appreciated!
When I did this on the mn102, I created a "prologue" and "epilogue" insn that did not expose the details. Look at how unspecs are used.

Then use emit_insn (gen_prologue (...)) and emit_jump_insn (gen_epilogue)) or something along those lines.

jeff


Thanks for the response! Perhaps an UNSPEC insn is needed here because I have work to do on other passes too. For example, when the debug info is created, it's giving the wrong location (on the stack) for where some registers were saved.

But my primary question is about how to generate a jump at the end of the epilogue. The out-lined pro/epilogue stubs are not dynamically generated, they sit in libgcc and don't always do all of the work. When one of these functions' pro & epilogue are generated, I basically suck out the saves/restores that are handled by the out-lined stubs and let ix86_expand_pro/epilogue emit instructions for the rest. So the simplest case should look like this:

extern void a_sysv_func(void);
void __attribute__((__ms_abi__)) an_msabi_func(void)
{
  do_sysv_func();
}

Should become:

callq  __msabi_save_even
callq a_sysv_func
jmp    __msabi_restore_even

However, if any other registers are clobbered, they will be saved after the call to __msabi_save_even/odd and restored prior to the jmp to __msabi_restore_even/odd. Since these routines are not in the same translation unit, I had assumed that there was no way to create a LABEL_REF for them. This is what I'm currently doing to create a call:

sym = gen_rtx_SYMBOL_REF (Pmode, "_msabi_restore_even");
call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (QImode, sym), const0_rtx);
call_insn = emit_call_insn (call);

I had tried the following to create a jump, but I apparently didn't put it together correctly because recog didn't find an instruction for it later:

sym = gen_rtx_SYMBOL_REF (Pmode, "_msabi_restore_even");
set = gen_rtx_SET (VOIDmode, pc_rtx, sym);
SET_IS_RETURN_P(set) = true;
jump_insn = emit_jump_insn (set);

I also tried this making the symbol a MEM and I get "unrecognizable insn" for both of them. When I don't do the SET_IS_RETURN_P(set) = true I get a failed assertion in commit_one_edge_insertion. I would think that the solution would be very, very simple. Maybe there was never a reason to do this before on i386 and it was never added to i386.md?

Using a call marked as a sibling call creates the correct instruction (while screwing up other things):

    call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (QImode, sym), const0_rtx);
    insn = emit_call_insn (call);
    SIBLING_CALL_P(insn) = true;

So maybe i386.md just needs to have something added so that the jump will work with a symbol? Or is this something that *should* be done in an UNSPEC?

Daniel

Reply via email to