diff options
author | Ian Lance Taylor <iant@google.com> | 2016-11-22 17:58:04 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-11-22 17:58:04 +0000 |
commit | 9d1e3afb5484c71eaaea23fc3a4b86fe35418d43 (patch) | |
tree | 2110ef75ee2708c685482ea2ace4dfbf1461d4aa /gcc/go | |
parent | 6c7509bc070b29293ca9874518b89227ce05361c (diff) | |
download | gcc-9d1e3afb5484c71eaaea23fc3a4b86fe35418d43.zip gcc-9d1e3afb5484c71eaaea23fc3a4b86fe35418d43.tar.gz gcc-9d1e3afb5484c71eaaea23fc3a4b86fe35418d43.tar.bz2 |
runtime: rewrite panic/defer code from C to Go
The actual stack unwind code is still in C, but the rest of the code,
notably all the memory allocation, is now in Go. The names are changed
to the names used in the Go 1.7 runtime, but the code is necessarily
somewhat different.
The __go_makefunc_can_recover function is dropped, as the uses of it
were removed in https://golang.org/cl/198770044.
Reviewed-on: https://go-review.googlesource.com/33414
From-SVN: r242715
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 9 | ||||
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/backend.h | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 6 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 25 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 20 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 4 |
9 files changed, 46 insertions, 35 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 8a04707..825e4f0 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,8 @@ +2016-11-22 Ian Lance Taylor <iant@google.com> + + * go-gcc.cc (Gcc_backend::Gcc_backend): Add builtin function + __builtin_frame_address. + 2016-10-25 David Malcolm <dmalcolm@redhat.com> * go-lang.c (go_langhook_type_for_mode): Remove redundant cast diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 44daaa0..619499e 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -828,6 +828,15 @@ Gcc_backend::Gcc_backend() this->define_builtin(BUILT_IN_FRAME_ADDRESS, "__builtin_frame_address", NULL, t, false, false); + // The runtime calls __builtin_extract_return_addr when recording + // the address to which a function returns. + this->define_builtin(BUILT_IN_EXTRACT_RETURN_ADDR, + "__builtin_extract_return_addr", NULL, + build_function_type_list(ptr_type_node, + ptr_type_node, + NULL_TREE), + false, false); + // The compiler uses __builtin_trap for some exception handling // cases. this->define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL, diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index f0cbae6..212b9e9 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -bf4762823c4543229867436399be3ae30b4d13bb +7593cc83a03999331c5e2dc65a9306c5fe57dfd0 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 8c45b64..dacfe48 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -707,7 +707,7 @@ class Backend // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: - // try { UNDEFER; } catch { CHECK_DEFER; goto finish; } + // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } virtual Bstatement* function_defer_statement(Bfunction* function, Bexpression* undefer, Bexpression* check_defer, Location) = 0; diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc index bcea63d..6429a9a 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -280,7 +280,7 @@ Node::op_format() const { switch (e->func_expression()->runtime_code()) { - case Runtime::PANIC: + case Runtime::GOPANIC: op << "panic"; break; @@ -300,11 +300,11 @@ Node::op_format() const op << "make"; break; - case Runtime::DEFER: + case Runtime::DEFERPROC: op << "defer"; break; - case Runtime::RECOVER: + case Runtime::GORECOVER: op << "recover"; break; @@ -1189,7 +1189,7 @@ Escape_analysis_assign::expression(Expression** pexpr) { switch (fe->runtime_code()) { - case Runtime::PANIC: + case Runtime::GOPANIC: { // Argument could leak through recover. Node* panic_arg = Node::make_node(call->args()->front()); diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 1b0434e..35c3e74 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -8951,7 +8951,7 @@ Builtin_call_expression::do_get_backend(Translate_context* context) arg = Expression::convert_for_assignment(gogo, empty, arg, location); Expression* panic = - Runtime::make_call(Runtime::PANIC, location, 1, arg); + Runtime::make_call(Runtime::GOPANIC, location, 1, arg); return panic->get_backend(context); } @@ -8972,8 +8972,8 @@ Builtin_call_expression::do_get_backend(Translate_context* context) // because it changes whether it can recover a panic or not. // See test7 in test/recover1.go. Expression* recover = Runtime::make_call((this->is_deferred() - ? Runtime::DEFERRED_RECOVER - : Runtime::RECOVER), + ? Runtime::DEFERREDRECOVER + : Runtime::GORECOVER), location, 0); Expression* cond = Expression::make_conditional(arg, recover, nil, location); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index acfab18..a9dd0a6 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -4168,8 +4168,7 @@ Build_recover_thunks::function(Named_object* orig_no) // Return the expression to pass for the .can_recover parameter to the // new function. This indicates whether a call to recover may return -// non-nil. The expression is -// __go_can_recover(__builtin_return_address()). +// non-nil. The expression is runtime.canrecover(__builtin_return_address()). Expression* Build_recover_thunks::can_recover_arg(Location location) @@ -4191,10 +4190,10 @@ Build_recover_thunks::can_recover_arg(Location location) results->push_back(Typed_identifier("", boolean_type, bloc)); Function_type* fntype = Type::make_function_type(NULL, param_types, results, bloc); - can_recover = Named_object::make_function_declaration("__go_can_recover", - NULL, fntype, - bloc); - can_recover->func_declaration_value()->set_asm_name("__go_can_recover"); + can_recover = + Named_object::make_function_declaration("runtime_canrecover", + NULL, fntype, bloc); + can_recover->func_declaration_value()->set_asm_name("runtime.canrecover"); } Expression* fn = Expression::make_func_reference(builtin_return_address, @@ -4217,10 +4216,10 @@ Build_recover_thunks::can_recover_arg(Location location) // function with an extra parameter, which is whether a call to // recover can succeed. We then move the body of this function to // that one. We then turn this function into a thunk which calls the -// new one, passing the value of -// __go_can_recover(__builtin_return_address()). The function will be -// marked as not splitting the stack. This will cooperate with the -// implementation of defer to make recover do the right thing. +// new one, passing the value of runtime.canrecover(__builtin_return_address()). +// The function will be marked as not splitting the stack. This will +// cooperate with the implementation of defer to make recover do the +// right thing. void Gogo::build_recover_thunks() @@ -5634,7 +5633,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function, // libgo/runtime/go-unwind.c. std::vector<Bstatement*> stmts; - Expression* call = Runtime::make_call(Runtime::CHECK_DEFER, end_loc, 1, + Expression* call = Runtime::make_call(Runtime::CHECKDEFER, end_loc, 1, this->defer_stack(end_loc)); Translate_context context(gogo, named_function, NULL, NULL); Bexpression* defer = call->get_backend(&context); @@ -5647,11 +5646,11 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function, go_assert(*except == NULL); *except = gogo->backend()->statement_list(stmts); - call = Runtime::make_call(Runtime::CHECK_DEFER, end_loc, 1, + call = Runtime::make_call(Runtime::CHECKDEFER, end_loc, 1, this->defer_stack(end_loc)); defer = call->get_backend(&context); - call = Runtime::make_call(Runtime::UNDEFER, end_loc, 1, + call = Runtime::make_call(Runtime::DEFERRETURN, end_loc, 1, this->defer_stack(end_loc)); Bexpression* undefer = call->get_backend(&context); Bstatement* function_defer = diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 5d3ce677..7027989 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -173,29 +173,26 @@ DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P1(POINTER), R1(INT32)) // Panic. -DEF_GO_RUNTIME(PANIC, "__go_panic", P1(EFACE), R0()) +DEF_GO_RUNTIME(GOPANIC, "runtime.gopanic", P1(EFACE), R0()) // Recover. -DEF_GO_RUNTIME(RECOVER, "__go_recover", P0(), R1(EFACE)) +DEF_GO_RUNTIME(GORECOVER, "runtime.gorecover", P0(), R1(EFACE)) // Recover when called directly from defer. -DEF_GO_RUNTIME(DEFERRED_RECOVER, "__go_deferred_recover", P0(), R1(EFACE)) +DEF_GO_RUNTIME(DEFERREDRECOVER, "runtime.deferredrecover", P0(), R1(EFACE)) // Decide whether this function can call recover. -DEF_GO_RUNTIME(CAN_RECOVER, "__go_can_recover", P1(POINTER), R1(BOOL)) - -// Get the return address of the function. -DEF_GO_RUNTIME(RETURN_ADDRESS, "__go_return_address", P1(INT), R1(POINTER)) +DEF_GO_RUNTIME(CANRECOVER, "runtime.canrecover", P1(POINTER), R1(BOOL)) // Set the return address for defer in a defer thunk. -DEF_GO_RUNTIME(SET_DEFER_RETADDR, "__go_set_defer_retaddr", P1(POINTER), +DEF_GO_RUNTIME(SETDEFERRETADDR, "runtime.setdeferretaddr", P1(POINTER), R1(BOOL)) // Check for a deferred function in an exception handler. -DEF_GO_RUNTIME(CHECK_DEFER, "__go_check_defer", P1(BOOLPTR), R0()) +DEF_GO_RUNTIME(CHECKDEFER, "runtime.checkdefer", P1(BOOLPTR), R0()) // Run deferred functions. -DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(BOOLPTR), R0()) +DEF_GO_RUNTIME(DEFERRETURN, "runtime.deferreturn", P1(BOOLPTR), R0()) // Panic with a runtime error. DEF_GO_RUNTIME(RUNTIME_ERROR, "__go_runtime_error", P1(INT32), R0()) @@ -233,7 +230,8 @@ DEF_GO_RUNTIME(NEW, "__go_new", P2(TYPE, UINTPTR), R1(POINTER)) DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0()) // Defer a function. -DEF_GO_RUNTIME(DEFER, "__go_defer", P3(BOOLPTR, FUNC_PTR, POINTER), R0()) +DEF_GO_RUNTIME(DEFERPROC, "runtime.deferproc", P3(BOOLPTR, FUNC_PTR, POINTER), + R0()) // Convert an empty interface to an empty interface, returning ok. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index e36262d..e25fd6b 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -2296,7 +2296,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name) { retaddr_label = gogo->add_label_reference("retaddr", location, false); Expression* arg = Expression::make_label_addr(retaddr_label, location); - Expression* call = Runtime::make_call(Runtime::SET_DEFER_RETADDR, + Expression* call = Runtime::make_call(Runtime::SETDEFERRETADDR, location, 1, arg); // This is a hack to prevent the middle-end from deleting the @@ -2540,7 +2540,7 @@ Defer_statement::do_get_backend(Translate_context* context) Location loc = this->location(); Expression* ds = context->function()->func_value()->defer_stack(loc); - Expression* call = Runtime::make_call(Runtime::DEFER, loc, 3, + Expression* call = Runtime::make_call(Runtime::DEFERPROC, loc, 3, ds, fn, arg); Bexpression* bcall = call->get_backend(context); return context->backend()->expression_statement(bcall); |