summaryrefslogtreecommitdiffstats
path: root/libgo/runtime/go-deferred-recover.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-03 04:34:57 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2010-12-03 04:34:57 +0000
commite440a3286bc89368b8d3a8fd6accd47191790bf2 (patch)
tree38fe54a4f38ede5d949c915d66191f24a6fe5153 /libgo/runtime/go-deferred-recover.c
parenta641ee368e2614349084a9a7bda2ec2b0b2bc1cf (diff)
downloadppe42-gcc-e440a3286bc89368b8d3a8fd6accd47191790bf2.tar.gz
ppe42-gcc-e440a3286bc89368b8d3a8fd6accd47191790bf2.zip
Add Go frontend, libgo library, and Go testsuite.
gcc/: * gcc.c (default_compilers): Add entry for ".go". * common.opt: Add -static-libgo as a driver option. * doc/install.texi (Configuration): Mention libgo as an option for --enable-shared. Mention go as an option for --enable-languages. * doc/invoke.texi (Overall Options): Mention .go as a file name suffix. Mention go as a -x option. * doc/frontends.texi (G++ and GCC): Mention Go as a supported language. * doc/sourcebuild.texi (Top Level): Mention libgo. * doc/standards.texi (Standards): Add section on Go language. Move references for other languages into their own section. * doc/contrib.texi (Contributors): Mention that I contributed the Go frontend. gcc/testsuite/: * lib/go.exp: New file. * lib/go-dg.exp: New file. * lib/go-torture.exp: New file. * lib/target-supports.exp (check_compile): Match // Go. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167407 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime/go-deferred-recover.c')
-rw-r--r--libgo/runtime/go-deferred-recover.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/libgo/runtime/go-deferred-recover.c b/libgo/runtime/go-deferred-recover.c
new file mode 100644
index 00000000000..2d9ca1442fc
--- /dev/null
+++ b/libgo/runtime/go-deferred-recover.c
@@ -0,0 +1,92 @@
+/* go-deferred-recover.c -- support for a deferred recover function.
+
+ Copyright 2010 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file. */
+
+#include <stddef.h>
+
+#include "go-panic.h"
+#include "go-defer.h"
+
+/* This is called when a call to recover is deferred. That is,
+ something like
+ defer recover()
+
+ We need to handle this specially. In 6g/8g, the recover function
+ looks up the stack frame. In particular, that means that a
+ deferred recover will not recover a panic thrown in the same
+ function that defers the recover. It will only recover a panic
+ thrown in a function that defers the deferred call to recover.
+
+ In other words:
+
+ func f1() {
+ defer recover() // does not stop panic
+ panic(0)
+ }
+
+ func f2() {
+ defer func() {
+ defer recover() // stops panic(0)
+ }()
+ panic(0)
+ }
+
+ func f3() {
+ defer func() {
+ defer recover() // does not stop panic
+ panic(0)
+ }()
+ panic(1)
+ }
+
+ func f4() {
+ defer func() {
+ defer func() {
+ defer recover() // stops panic(0)
+ }()
+ panic(0)
+ }()
+ panic(1)
+ }
+
+ The interesting case here is f3. As can be seen from f2, the
+ deferred recover could pick up panic(1). However, this does not
+ happen because it is blocked by the panic(0).
+
+ When a function calls recover, then when we invoke it we pass a
+ hidden parameter indicating whether it should recover something.
+ This parameter is set based on whether the function is being
+ invoked directly from defer. The parameter winds up determining
+ whether __go_recover or __go_deferred_recover is called at all.
+
+ In the case of a deferred recover, the hidden parameter which
+ controls the call is actually the one set up for the function which
+ runs the defer recover() statement. That is the right thing in all
+ the cases above except for f3. In f3 the function is permitted to
+ call recover, but the deferred recover call is not. We address
+ that here by checking for that specific case before calling
+ recover. If this function was deferred when there is already a
+ panic on the panic stack, then we can only recover that panic, not
+ any other.
+
+ Note that we can get away with using a special function here
+ because you are not permitted to take the address of a predeclared
+ function like recover. */
+
+struct __go_empty_interface
+__go_deferred_recover ()
+{
+ if (__go_panic_defer == NULL
+ || __go_panic_defer->__defer == NULL
+ || __go_panic_defer->__defer->__panic != __go_panic_defer->__panic)
+ {
+ struct __go_empty_interface ret;
+
+ ret.__type_descriptor = NULL;
+ ret.__object = NULL;
+ return ret;
+ }
+ return __go_recover();
+}
OpenPOWER on IntegriCloud