Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
b9f04a84
Commit
b9f04a84
authored
Sep 16, 2011
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix defer when not calling recover in function with named results.
From-SVN: r178905
parent
fae3f459
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
57 additions
and
27 deletions
+57
-27
gcc/go/gofrontend/gogo-tree.cc
+14
-4
gcc/go/gofrontend/gogo.cc
+9
-9
gcc/go/gofrontend/runtime.def
+3
-3
gcc/go/gofrontend/statements.cc
+4
-5
libgo/runtime/go-defer.c
+8
-2
libgo/runtime/go-defer.h
+4
-3
libgo/runtime/go-panic.c
+6
-0
libgo/runtime/go-unwind.c
+9
-1
No files found.
gcc/go/gofrontend/gogo-tree.cc
View file @
b9f04a84
...
...
@@ -1592,15 +1592,25 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
&&
!
this
->
type_
->
results
()
->
empty
()
&&
!
this
->
type_
->
results
()
->
front
().
name
().
empty
())
{
// If the result variables are named, we need to return them
// again, because they might have been changed by a defer
// function.
// If the result variables are named, and we are returning from
// this function rather than panicing through it, we need to
// return them again, because they might have been changed by a
// defer function. The runtime routines set the defer_stack
// variable to true if we are returning from this function.
retval
=
this
->
return_value
(
gogo
,
named_function
,
end_loc
,
&
stmt_list
);
set
=
fold_build2_loc
(
end_loc
,
MODIFY_EXPR
,
void_type_node
,
DECL_RESULT
(
this
->
fndecl_
),
retval
);
ret_stmt
=
fold_build1_loc
(
end_loc
,
RETURN_EXPR
,
void_type_node
,
set
);
append_to_statement_list
(
ret_stmt
,
&
stmt_list
);
Expression
*
ref
=
Expression
::
make_temporary_reference
(
this
->
defer_stack_
,
end_loc
);
tree
tref
=
ref
->
get_tree
(
&
context
);
tree
s
=
build3_loc
(
end_loc
,
COND_EXPR
,
void_type_node
,
tref
,
ret_stmt
,
NULL_TREE
);
append_to_statement_list
(
s
,
&
stmt_list
);
}
go_assert
(
*
fini
==
NULL_TREE
);
...
...
gcc/go/gofrontend/gogo.cc
View file @
b9f04a84
...
...
@@ -2976,27 +2976,27 @@ Function::determine_types()
this
->
block_
->
determine_types
();
}
// Get a pointer to the variable holding the defer stack for this
// function, making it if necessary. At least at present, the value
// of this variable is not used. However, a pointer to this variable
// is used as a marker for the functions on the defer stack associated
// with this function. Doing things this way permits inlining a
// Get a pointer to the variable representing the defer stack for this
// function, making it if necessary. The value of the variable is set
// by the runtime routines to true if the function is returning,
// rather than panicing through. A pointer to this variable is used
// as a marker for the functions on the defer stack associated with
// this function. A function-specific variable permits inlining a
// function which uses defer.
Expression
*
Function
::
defer_stack
(
source_location
location
)
{
Type
*
t
=
Type
::
make_pointer_type
(
Type
::
make_void_type
());
if
(
this
->
defer_stack_
==
NULL
)
{
Expression
*
n
=
Expression
::
make_nil
(
location
);
Type
*
t
=
Type
::
lookup_bool_type
();
Expression
*
n
=
Expression
::
make_boolean
(
false
,
location
);
this
->
defer_stack_
=
Statement
::
make_temporary
(
t
,
n
,
location
);
this
->
defer_stack_
->
set_is_address_taken
();
}
Expression
*
ref
=
Expression
::
make_temporary_reference
(
this
->
defer_stack_
,
location
);
Expression
*
addr
=
Expression
::
make_unary
(
OPERATOR_AND
,
ref
,
location
);
return
Expression
::
make_unsafe_cast
(
t
,
addr
,
location
);
return
Expression
::
make_unary
(
OPERATOR_AND
,
ref
,
location
);
}
// Export the function.
...
...
gcc/go/gofrontend/runtime.def
View file @
b9f04a84
...
...
@@ -165,10 +165,10 @@ DEF_GO_RUNTIME(SET_DEFER_RETADDR, "__go_set_defer_retaddr", P1(POINTER),
R1(BOOL))
// Check for a deferred function in an exception handler.
DEF_GO_RUNTIME(CHECK_DEFER, "__go_check_defer", P1(
POINTE
R), R0())
DEF_GO_RUNTIME(CHECK_DEFER, "__go_check_defer", P1(
BOOLPT
R), R0())
// Run deferred functions.
DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(
POINTE
R), R0())
DEF_GO_RUNTIME(UNDEFER, "__go_undefer", P1(
BOOLPT
R), R0())
// Panic with a runtime error.
DEF_GO_RUNTIME(RUNTIME_ERROR, "__go_runtime_error", P1(INT), R0())
...
...
@@ -207,7 +207,7 @@ DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
// Defer a function.
DEF_GO_RUNTIME(DEFER, "__go_defer", P3(
POINTE
R, FUNC_PTR, POINTER), R0())
DEF_GO_RUNTIME(DEFER, "__go_defer", P3(
BOOLPT
R, FUNC_PTR, POINTER), R0())
// Run a select statement.
...
...
gcc/go/gofrontend/statements.cc
View file @
b9f04a84
...
...
@@ -2539,11 +2539,10 @@ Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
// Lower a return statement. If we are returning a function call
// which returns multiple values which match the current function,
// split up the call's results. If the function has named result
// variables, and the return statement lists explicit values, then
// implement it by assigning the values to the result variables and
// changing the statement to not list any values. This lets
// panic/recover work correctly.
// split up the call's results. If the return statement lists
// explicit values, implement this statement by assigning the values
// to the result variables and change this statement to a naked
// return. This lets panic/recover work correctly.
Statement
*
Return_statement
::
do_lower
(
Gogo
*
,
Named_object
*
function
,
Block
*
enclosing
,
...
...
libgo/runtime/go-defer.c
View file @
b9f04a84
...
...
@@ -13,7 +13,7 @@
/* This function is called each time we need to defer a call. */
void
__go_defer
(
void
*
frame
,
void
(
*
pfn
)
(
void
*
),
void
*
arg
)
__go_defer
(
_Bool
*
frame
,
void
(
*
pfn
)
(
void
*
),
void
*
arg
)
{
struct
__go_defer_stack
*
n
;
...
...
@@ -34,7 +34,7 @@ __go_defer (void *frame, void (*pfn) (void *), void *arg)
/* This function is called when we want to undefer the stack. */
void
__go_undefer
(
void
*
frame
)
__go_undefer
(
_Bool
*
frame
)
{
if
(
__go_panic_defer
==
NULL
)
return
;
...
...
@@ -53,6 +53,12 @@ __go_undefer (void *frame)
__go_panic_defer
->
__defer
=
d
->
__next
;
__go_free
(
d
);
/* Since we are executing a defer function here, we know we are
returning from the calling function. If the calling
function, or one of its callees, paniced, then the defer
functions would be executed by __go_panic. */
*
frame
=
1
;
}
}
...
...
libgo/runtime/go-defer.h
View file @
b9f04a84
...
...
@@ -13,9 +13,10 @@ struct __go_defer_stack
/* The next entry in the stack. */
struct
__go_defer_stack
*
__next
;
/* The frame pointer for the function which called this defer
statement. */
void
*
__frame
;
/* The stack variable for the function which called this defer
statement. This is set to 1 if we are returning from that
function, 0 if we are panicing through it. */
_Bool
*
__frame
;
/* The value of the panic stack when this function is deferred.
This function can not recover this value from the panic stack.
...
...
libgo/runtime/go-panic.c
View file @
b9f04a84
...
...
@@ -87,6 +87,12 @@ __go_panic (struct __go_empty_interface arg)
/* __go_unwind_stack should not return. */
abort
();
}
/* Because we executed that defer function by a panic, and
it did not call recover, we know that we are not
returning from the calling function--we are panicing
through it. */
*
d
->
__frame
=
0
;
}
__go_panic_defer
->
__defer
=
d
->
__next
;
...
...
libgo/runtime/go-unwind.c
View file @
b9f04a84
...
...
@@ -44,7 +44,7 @@ static const _Unwind_Exception_Class __go_exception_class =
continue unwinding. */
void
__go_check_defer
(
void
*
frame
)
__go_check_defer
(
_Bool
*
frame
)
{
struct
_Unwind_Exception
*
hdr
;
...
...
@@ -103,8 +103,12 @@ __go_check_defer (void *frame)
if
(
was_recovered
)
{
/* Just return and continue executing Go code. */
*
frame
=
1
;
return
;
}
/* We are panicing through this function. */
*
frame
=
0
;
}
else
if
(
__go_panic_defer
->
__defer
!=
NULL
&&
__go_panic_defer
->
__defer
->
__pfn
==
NULL
...
...
@@ -118,6 +122,10 @@ __go_check_defer (void *frame)
d
=
__go_panic_defer
->
__defer
;
__go_panic_defer
->
__defer
=
d
->
__next
;
__go_free
(
d
);
/* We are returning from this function. */
*
frame
=
1
;
return
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment