0db9e20bfb
For several years I've been eager to find the time to fix the bugs in C++ exceptions on VAX to get them working on NetBSD, because theyâve been broken for many years and it looked like only a few changes were needed to get them working. Without C++ exceptions, the NetBSD test suite canât be run. The good news is that I was able to fix all the bugs in the VAX machine description to make C++ exceptions work in GCC 4.8.5 (version unimportant). I wrote a blog post explaining the bugs, with patches: Here's a short summary, with the diffs in text form at the end of this email. 1) Replace #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0 with #define ARG_POINTER_CFA_OFFSET(FNDECL) 0 in gcc/config/vax/elf.h and gcc/config/vax/vax.h. This changes the definition of __builtin_dwarf_cfa() to return %ap instead of %fp, which correctly points to CFA. Previously, the stack unwinder was crashing in _Unwind_RaiseException() trying to follow bad pointers from the initial CFA. 2) Define EH_RETURN_DATA_REGNO(N) to include only R2 and R3 (instead of R2-R5) and add code to vax_expand_prologue() in gcc/config/vax/vax.c to add R2-R3 to the procedure entry mask but only if crtl->calls_eh_return is set. This fixes a crash when the stack unwinder tried to write values to R2 and R3 in the previous stack frame via __builtin_eh_return_data_regno (0) and __builtin_eh_return_data_regno (1). 3) Removed definitions of EH_RETURN_STACKADJ_RTX and STARTING_FRAME_OFFSET from gcc/config/vax/elf.h. It's not necessary to remember the stack adjustment or to waste four bytes on every stack frame for a value that's not needed. Also remove the suspicious changes in gcc/config/vax/vax.md to the definitions of call_pop and call_value regarding DW_CFA_GNU_args_size and EH unwinding. I reverted to the previous versions from an older version of GCC, adding a few useful comments that had been removed. 4) The last bug is the one I understand the least. I'm hoping someone reading this can implement a correct fix. What I was seeing after making all the previous changes to fix the other bugs is that my test program failed to catch any exceptions, but instead returned normally to the original return path. Investigation revealed that GCC was correctly generating the necessary move instruction to copy the second parameter passed to __builtin_eh_return() into the return address, because EH_RETURN_HANDLER_RTX had been defined correctly in config/vax/elf.h. Hereâs what the call looks like in gcc/except.c: #ifdef EH_RETURN_HANDLER_RTX rtx insn = emit_move_insn (EH_RETURN_HANDLER_RTX, crtl->eh.ehr_handler); #else error ("__builtin_eh_return not supported on this target"); #endif The problem was that the optimizer is deleting the final move instruction when I compile with -O or higher. The assembly code at -O0 (no optimization) generated for the __builtin_eh_return() call at the end of _Unwind_RaiseException() looked like: calls $2,_Unwind_DebugHook movl -12(%fp),%r1 movl %r1,16(%fp) ret .cfi_endproc But then when I compiled with -O1 or -O2, all I saw was: calls $2,_Unwind_DebugHook ret .cfi_endproc This was a mystery for me and I donât know enough about how the final peephole optimizer works to really track down why it thinks it can remove the move call to store the previous return address. My workaround was to add a call to RTX_FRAME_RELATED_P (insn) = 1; after the emit_move_insn() in gcc/except.c, which was used in vax_expand_prologue() to mark the procedure entry mask. By making this change, the optimizer no longer removes the call to write the value to the previous stack pointer, but it adds an extra line of .cfi exception info, which seems unnecessary since the code is immediately going to return from the call and any adjustment made by the DWARF stack unwinder will already have been done. Hereâs what the optimized code looks like with the patch (%r6 had been loaded earlier): calls $2,_Unwind_DebugHook movl %r6,16(%fp) .cfi_offset 6, -36 ret .cfi_endproc With that final change, C++ exception handling now finally works on NetBSD/vax, and I was able to successfully run the vast majority of the tests in the ATF testsuite, which had been completely inaccessible when I started due to both atf-run and atf-report immediately dumping core due to the bad pointers that I fixed. Now I have a bunch of new bugs to track down fixes for, but I think this was the hardest set of problems that needed to be solved to bring NetBSD on VAX up to the level of the other NetBSD ports. Here are the diffs I have so far. They should apply to any recent version of GCC (tested on GCC 4.8.5). With the exception of the hack to gcc/except.c, the other diffs are ready to submit to NetBSD as well as to upstream GCC. The fix Iâd like to see for the final problem I discovered of the emit_move_insn() being deleted by the optimizer would be another patch to one of the files in the gcc/config/vax directory to explain to the optimizer that writing to 16(%fp) is important and not something to be deleted from the epilogue (perhaps it thinks itâs writing to a local variable in the frame that's about to be destroyed?). I didn't see any indication that any other GCC ports required anything special to tell the optimizer not to delete the move instruction to EH_RETURN_HANDLER_RTX, so the other suspicion I have is that there may be a bug specific to VAX's peephole optimizer or related functions. Any ideas? |
||
---|---|---|
.. | ||
apache2 | ||
atheros | ||
broadcom/rpi-firmware/dist | ||
bsd | ||
cddl | ||
gpl2 | ||
gpl3 | ||
historical | ||
ibm-public | ||
intel-fw-eula | ||
intel-fw-public | ||
lgpl3 | ||
mit | ||
public-domain | ||
realtek | ||
zlib/pigz | ||
Makefile | ||
README |
$NetBSD: README,v 1.15 2012/06/14 04:14:36 riz Exp $ Organization of Sources: This directory hierarchy is using an organization that separates source for programs that we have obtained from external third parties (where NetBSD is not the primary maintainer) from the system source. The hierarchy is grouped by license, and then package per license, and is organized as follows: external/ Makefile Descend into the license sub-directories. <license>/ Per-license sub-directories. Makefile Descend into the package sub-directories. <package>/ Per-package sub-directories. Makefile Build the package. dist/ The third-party source for a given package. bin/ lib/ sbin/ BSD makefiles "reach over" from these into "../dist/". This arrangement allows for packages to be easily disabled or excised as necessary, either on a per-license or per-package basis. The licenses currently used are: apache2 Apache 2.0 license. http://www.opensource.org/licenses/apache2.0.php atheros Atheros License. bsd BSD (or equivalent) licensed software, possibly with the "advertising clause". http://www.opensource.org/licenses/bsd-license.php cddl Common Development and Distribution License (the sun license which is based on the Mozilla Public License version 1.1). http://www.opensource.org/licenses/cddl1.php gpl2 GNU Public License, version 2 (or earlier). http://www.opensource.org/licenses/gpl-2.0.php gpl3 GNU Public License, version 3. http://www.opensource.org/licenses/gpl-3.0.html historical Lucent's old license: http://www.opensource.org/licenses/historical.php ibm-public IBM's public license: http://www.opensource.org/licenses/ibmpl.php intel-fw-eula Intel firmware license with redistribution restricted to OEM. intel-fw-public Intel firmware license permitting redistribution with terms similar to BSD licensed software. intel-public Intel license permitting redistribution with terms similar to BSD licensed software. mit MIT (X11) style license. http://www.opensource.org/licenses/mit-license.php public-domain Non-license for code that has been explicitly put into the Public Domain. realtek RealTek license. zlib Zlib (BSD-like) license. http://www.zlib.net/zlib_license.html If a package has components covered by different licenses (for example, GPL2 and the LGPL), use the <license> subdirectory for the more restrictive license. If a package allows the choice of a license to use, we'll generally use the less restrictive license. If in doubt about where a package should be located, please contact <core@NetBSD.org> for advice. Migration Strategy: Eventually src/dist (and associated framework in other base source directories) and src/gnu will be migrated to this hierarchy. Maintenance Strategy: The sources under src/external/<license>/<package>/dist/ are generally a combination of a published distribution plus changes that we submit to the maintainers and that are not yet published by them. Make sure all changes made to the external sources are submitted to the appropriate maintainer, but only after coordinating with the NetBSD maintainers.