aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-11-22 17:58:04 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-11-22 17:58:04 +0000
commit9d1e3afb5484c71eaaea23fc3a4b86fe35418d43 (patch)
tree2110ef75ee2708c685482ea2ace4dfbf1461d4aa /gcc/go
parent6c7509bc070b29293ca9874518b89227ce05361c (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/go/go-gcc.cc9
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/backend.h2
-rw-r--r--gcc/go/gofrontend/escape.cc8
-rw-r--r--gcc/go/gofrontend/expressions.cc6
-rw-r--r--gcc/go/gofrontend/gogo.cc25
-rw-r--r--gcc/go/gofrontend/runtime.def20
-rw-r--r--gcc/go/gofrontend/statements.cc4
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);