Path: utzoo!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!rpi!uupsi!sunic!fuug!funic!santra!news From: jkp@cs.HUT.FI (Jyrki Kuoppala) Newsgroups: comp.os.minix Subject: A patch to make gcc 1.39 work with Minix setjmp Message-ID: <1991Mar10.223859.380@santra.uucp> Date: 10 Mar 91 22:38:59 GMT Sender: news@santra.uucp (Cnews - USENET news system) Reply-To: jkp@cs.HUT.FI (Jyrki Kuoppala) Organization: Helsinki University of Technology, Finland Lines: 146 As distributed, Minix (1.5.10 and I think also 1.3) setjmp library routine doesn't save the registers which are not allowed to be clobbered by the called function. Generally, Unix saves all registers in setjmp. In my opinion, both of these methods seem to be about as good, also there are some points to support the Minix style. However, the compiler must be aware of when setjmp is called and must generate code to save the registers which are not allowed to be clobbered by the function. Otherwise trouble is on the way. This kept me puzzled for a long time when I was porting emacs 18.57 to the pc532, and didn't yet have a working debugger. This diff makes gcc work right on those machines where the library routine `setjmp' doesn't save registers and `longjmp' doesn't do stack unwinding. Normally on these machines / environments code using `setjmp' fails if compiled with gcc, because call-saved registers are not saved in the function calling `setjmp' if they are not used. But they might be used in functions called from the function calling `setjmp' - the trouble is they never get restored when longjmp is called. This problem seems to exist at least on Minix, where the normal `setjmp' library function doesn't save the registers. There is no problem with the normal Minix compilers (I think), because they (I'm told at least ACK and Bruce Evans's bcc) save all regs in the prologue of a function calling `setjmp'. There really is no requirement to save all the registers in `setjmp'. The tradition in Unix seems to be that all registers are saved - I'm told that in BSD this might be because partly the same mechanism is used for handling signals and handling `setjmp'. Of course in signal handling it's a must to save all the registers. There's no big difference to do it either way. Perhaps to do it with a `setjmp' not saving registers is a bit more efficient, because then some registers don't have to be saved twice (first in the function prologue for those used in the function, then all registers in `setjmp'). If `setjmp' is called several times in a function, non-reg-saving `setjmp' is also a win. This modification requires reliable detection of `setjmp' by gcc. This is possible to do, because ANSI says that `setjmp' is a macro defined in . So `setjmp' can never be called via a pointer. Gcc currently (as of version 1.39) detects calls to `setjmp' by examining if the function called is named "setjmp" or "_setjmp" (see expr.c). If `setjmp' is defined differently in your , you have to modify either the definition or gcc to make the detection work. To tell gcc that your setjmp does not save all regs, add the line: #define NON_REG_SAVING_SETJMP to your tm.h file. I have submitted this patch to gcc maintainers, so it might be included in a future gcc release if considered useful. This should be target machine-independent, but any bug reports are welcome. *** orig/final.c Mon Aug 6 22:12:00 1990 --- final.c Mon Mar 4 21:15:05 1991 *************** *** 42,71 **** --- 42,74 ---- The code for the function prologue and epilogue are generated directly as assembler code by the macros FUNCTION_PROLOGUE and FUNCTION_EPILOGUE. Those instructions never exist as rtl. */ #include #include "config.h" #include "rtl.h" #include "regs.h" #include "insn-config.h" #include "recog.h" #include "conditions.h" #include "gdbfiles.h" #include "flags.h" #include "real.h" #include "output.h" + #ifdef NON_REG_SAVING_SETJMP + #include "hard-reg-set.h" + #endif /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */ #ifdef DBX_DEBUGGING_INFO #ifdef USG #include "stab.h" /* If doing DBX on sysV, use our own stab.h. */ #else #include /* On BSD, use the system's stab.h. */ #endif /* not USG */ #endif /* DBX_DEBUGGING_INFO */ /* .stabd code for line number. */ #ifndef N_SLINE #define N_SLINE 0x44 #endif *************** *** 361,390 **** --- 364,404 ---- FILE is the file to write assembler code to. WRITE_SYMBOLS says which kind of debugging info to write (or none). OPTIMIZE is nonzero if we should eliminate redundant test and compare insns. */ void final_start_function (first, file, write_symbols, optimize) rtx first; FILE *file; enum debugger write_symbols; int optimize; { block_depth = 0; this_is_asm_operands = 0; + + #ifdef NON_REG_SAVING_SETJMP + if (current_function_calls_setjmp) + { + int i; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (!call_used_regs[i] && !call_fixed_regs[i]) + regs_ever_live[i] = 1; + } + #endif /* Record beginning of the symbol-block that's the entire function. */ if (write_symbols == GDB_DEBUG) { pending_blocks[block_depth++] = next_block_index; fprintf (file, "\t.gdbbeg %d\n", next_block_index++); } /* Initial line number is supposed to be output before the function's prologue and label so that the function's address will not appear to be in the last statement of the preceding function. */ if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED) { -- Jyrki Kuoppala Helsinki University of Technology, Finland. Internet : jkp@cs.hut.fi [130.233.251.253] X400 : /C=fi/A=fumail/P=inet/O=hut/OU=cs/S=Kuoppala/G=Jyrki BITNET : jkp@fingate.bitnet Gravity is a myth, the Earth sucks!