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
48ab8ba6
Commit
48ab8ba6
authored
Aug 25, 2011
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Change Bound_method_expression to refer to a constant method.
From-SVN: r178091
parent
2e335040
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
121 additions
and
98 deletions
+121
-98
gcc/go/gofrontend/expressions.cc
+38
-22
gcc/go/gofrontend/expressions.h
+7
-8
gcc/go/gofrontend/statements.cc
+68
-52
gcc/go/gofrontend/statements.h
+5
-9
gcc/go/gofrontend/types.cc
+3
-7
No files found.
gcc/go/gofrontend/expressions.cc
View file @
48ab8ba6
...
...
@@ -6798,9 +6798,7 @@ Expression::comparison_tree(Translate_context* context, Operator op,
int
Bound_method_expression
::
do_traverse
(
Traverse
*
traverse
)
{
if
(
Expression
::
traverse
(
&
this
->
expr_
,
traverse
)
==
TRAVERSE_EXIT
)
return
TRAVERSE_EXIT
;
return
Expression
::
traverse
(
&
this
->
method_
,
traverse
);
return
Expression
::
traverse
(
&
this
->
expr_
,
traverse
);
}
// Return the type of a bound method expression. The type of this
...
...
@@ -6811,7 +6809,12 @@ Bound_method_expression::do_traverse(Traverse* traverse)
Type
*
Bound_method_expression
::
do_type
()
{
return
this
->
method_
->
type
();
if
(
this
->
method_
->
is_function
())
return
this
->
method_
->
func_value
()
->
type
();
else
if
(
this
->
method_
->
is_function_declaration
())
return
this
->
method_
->
func_declaration_value
()
->
type
();
else
return
Type
::
make_error_type
();
}
// Determine the types of a method expression.
...
...
@@ -6819,9 +6822,7 @@ Bound_method_expression::do_type()
void
Bound_method_expression
::
do_determine_type
(
const
Type_context
*
)
{
this
->
method_
->
determine_type_no_context
();
Type
*
mtype
=
this
->
method_
->
type
();
Function_type
*
fntype
=
mtype
==
NULL
?
NULL
:
mtype
->
function_type
();
Function_type
*
fntype
=
this
->
type
()
->
function_type
();
if
(
fntype
==
NULL
||
!
fntype
->
is_method
())
this
->
expr_
->
determine_type_no_context
();
else
...
...
@@ -6836,14 +6837,12 @@ Bound_method_expression::do_determine_type(const Type_context*)
void
Bound_method_expression
::
do_check_types
(
Gogo
*
)
{
Type
*
type
=
this
->
method_
->
type
()
->
deref
();
if
(
type
==
NULL
||
type
->
function_type
()
==
NULL
||
!
type
->
function_type
()
->
is_method
())
if
(
!
this
->
method_
->
is_function
()
&&
!
this
->
method_
->
is_function_declaration
())
this
->
report_error
(
_
(
"object is not a method"
));
else
{
Type
*
rtype
=
t
ype
->
function_type
()
->
receiver
()
->
type
()
->
deref
();
Type
*
rtype
=
t
his
->
type
()
->
function_type
()
->
receiver
()
->
type
()
->
deref
();
Type
*
etype
=
(
this
->
expr_type_
!=
NULL
?
this
->
expr_type_
:
this
->
expr_
->
type
());
...
...
@@ -6881,14 +6880,13 @@ Bound_method_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
ast_dump_context
->
ostream
()
<<
")"
;
}
ast_dump_context
->
ostream
()
<<
"."
;
ast_dump_context
->
dump_expression
(
method_
);
ast_dump_context
->
ostream
()
<<
"."
<<
this
->
method_
->
name
();
}
// Make a method expression.
Bound_method_expression
*
Expression
::
make_bound_method
(
Expression
*
expr
,
Expression
*
method
,
Expression
::
make_bound_method
(
Expression
*
expr
,
Named_object
*
method
,
source_location
location
)
{
return
new
Bound_method_expression
(
expr
,
method
,
location
);
...
...
@@ -9257,6 +9255,9 @@ Call_expression::bound_method_function(Translate_context* context,
Bound_method_expression
*
bound_method
,
tree
*
first_arg_ptr
)
{
Gogo
*
gogo
=
context
->
gogo
();
source_location
loc
=
this
->
location
();
Expression
*
first_argument
=
bound_method
->
first_argument
();
tree
first_arg
=
first_argument
->
get_tree
(
context
);
if
(
first_arg
==
error_mark_node
)
...
...
@@ -9272,7 +9273,7 @@ Call_expression::bound_method_function(Translate_context* context,
||
TREE_CODE
(
first_arg
)
==
INDIRECT_REF
||
TREE_CODE
(
first_arg
)
==
COMPONENT_REF
)
{
first_arg
=
build_fold_addr_expr
(
first_arg
);
first_arg
=
build_fold_addr_expr
_loc
(
loc
,
first_arg
);
if
(
DECL_P
(
first_arg
))
TREE_ADDRESSABLE
(
first_arg
)
=
1
;
}
...
...
@@ -9282,9 +9283,10 @@ Call_expression::bound_method_function(Translate_context* context,
get_name
(
first_arg
));
DECL_IGNORED_P
(
tmp
)
=
0
;
DECL_INITIAL
(
tmp
)
=
first_arg
;
first_arg
=
build2
(
COMPOUND_EXPR
,
pointer_to_arg_type
,
build1
(
DECL_EXPR
,
void_type_node
,
tmp
),
build_fold_addr_expr
(
tmp
));
first_arg
=
build2_loc
(
loc
,
COMPOUND_EXPR
,
pointer_to_arg_type
,
build1_loc
(
loc
,
DECL_EXPR
,
void_type_node
,
tmp
),
build_fold_addr_expr_loc
(
loc
,
tmp
));
TREE_ADDRESSABLE
(
tmp
)
=
1
;
}
if
(
first_arg
==
error_mark_node
)
...
...
@@ -9296,8 +9298,8 @@ Call_expression::bound_method_function(Translate_context* context,
{
if
(
fatype
->
points_to
()
==
NULL
)
fatype
=
Type
::
make_pointer_type
(
fatype
);
Btype
*
bfatype
=
fatype
->
get_backend
(
context
->
gogo
()
);
first_arg
=
fold_convert
(
type_to_tree
(
bfatype
),
first_arg
);
Btype
*
bfatype
=
fatype
->
get_backend
(
gogo
);
first_arg
=
fold_convert
_loc
(
loc
,
type_to_tree
(
bfatype
),
first_arg
);
if
(
first_arg
==
error_mark_node
||
TREE_TYPE
(
first_arg
)
==
error_mark_node
)
return
error_mark_node
;
...
...
@@ -9305,7 +9307,21 @@ Call_expression::bound_method_function(Translate_context* context,
*
first_arg_ptr
=
first_arg
;
return
bound_method
->
method
()
->
get_tree
(
context
);
Named_object
*
method
=
bound_method
->
method
();
tree
id
=
method
->
get_id
(
gogo
);
if
(
id
==
error_mark_node
)
return
error_mark_node
;
tree
fndecl
;
if
(
method
->
is_function
())
fndecl
=
method
->
func_value
()
->
get_or_make_decl
(
gogo
,
method
,
id
);
else
if
(
method
->
is_function_declaration
())
fndecl
=
method
->
func_declaration_value
()
->
get_or_make_decl
(
gogo
,
method
,
id
);
else
go_unreachable
();
return
build_fold_addr_expr_loc
(
loc
,
fndecl
);
}
// Get the function and the first argument to use when calling an
...
...
gcc/go/gofrontend/expressions.h
View file @
48ab8ba6
...
...
@@ -192,7 +192,7 @@ class Expression
// Make an expression which is a method bound to its first
// parameter.
static
Bound_method_expression
*
make_bound_method
(
Expression
*
object
,
Expression
*
method
,
source_location
);
make_bound_method
(
Expression
*
object
,
Named_object
*
method
,
source_location
);
// Make an index or slice expression. This is a parser expression
// which represents LEFT[START:END]. END may be NULL, meaning an
...
...
@@ -1636,7 +1636,7 @@ class Map_index_expression : public Expression
class
Bound_method_expression
:
public
Expression
{
public
:
Bound_method_expression
(
Expression
*
expr
,
Expression
*
method
,
Bound_method_expression
(
Expression
*
expr
,
Named_object
*
method
,
source_location
location
)
:
Expression
(
EXPRESSION_BOUND_METHOD
,
location
),
expr_
(
expr
),
expr_type_
(
NULL
),
method_
(
method
)
...
...
@@ -1654,8 +1654,8 @@ class Bound_method_expression : public Expression
first_argument_type
()
const
{
return
this
->
expr_type_
;
}
// Return the
reference to the
method function.
Expression
*
// Return the method function.
Named_object
*
method
()
{
return
this
->
method_
;
}
...
...
@@ -1680,8 +1680,7 @@ class Bound_method_expression : public Expression
Expression
*
do_copy
()
{
return
new
Bound_method_expression
(
this
->
expr_
->
copy
(),
this
->
method_
->
copy
(),
return
new
Bound_method_expression
(
this
->
expr_
->
copy
(),
this
->
method_
,
this
->
location
());
}
...
...
@@ -1699,8 +1698,8 @@ class Bound_method_expression : public Expression
// NULL in the normal case, non-NULL when using a method from an
// anonymous field which does not require a stub.
Type
*
expr_type_
;
// The method itself.
This is a Func_expression.
Expression
*
method_
;
// The method itself.
Named_object
*
method_
;
};
// A reference to a field in a struct.
...
...
gcc/go/gofrontend/statements.cc
View file @
48ab8ba6
...
...
@@ -1808,10 +1808,6 @@ Statement::make_dec_statement(Expression* expr)
// Class Thunk_statement. This is the base class for go and defer
// statements.
const
char
*
const
Thunk_statement
::
thunk_field_fn
=
"fn"
;
const
char
*
const
Thunk_statement
::
thunk_field_receiver
=
"receiver"
;
// Constructor.
Thunk_statement
::
Thunk_statement
(
Statement_classification
classification
,
...
...
@@ -1991,6 +1987,30 @@ Gogo::simplify_thunk_statements()
this
->
traverse
(
&
thunk_traverse
);
}
// Return true if the thunk function is a constant, which means that
// it does not need to be passed to the thunk routine.
bool
Thunk_statement
::
is_constant_function
()
const
{
Call_expression
*
ce
=
this
->
call_
->
call_expression
();
Function_type
*
fntype
=
ce
->
get_function_type
();
if
(
fntype
==
NULL
)
{
go_assert
(
saw_errors
());
return
false
;
}
if
(
fntype
->
is_builtin
())
return
true
;
Expression
*
fn
=
ce
->
fn
();
if
(
fn
->
func_expression
()
!=
NULL
)
return
fn
->
func_expression
()
->
closure
()
==
NULL
;
if
(
fn
->
bound_method_expression
()
!=
NULL
||
fn
->
interface_field_reference_expression
()
!=
NULL
)
return
true
;
return
false
;
}
// Simplify complex thunk statements into simple ones. A complicated
// thunk statement is one which takes anything other than zero
// parameters or a single pointer parameter. We rewrite it into code
...
...
@@ -2031,14 +2051,13 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
Bound_method_expression
*
bound_method
=
fn
->
bound_method_expression
();
Interface_field_reference_expression
*
interface_method
=
fn
->
interface_field_reference_expression
();
const
bool
is_method
=
bound_method
!=
NULL
||
interface_method
!=
NULL
;
source_location
location
=
this
->
location
();
std
::
string
thunk_name
=
Gogo
::
thunk_name
();
// Build the thunk.
this
->
build_thunk
(
gogo
,
thunk_name
,
fntype
);
this
->
build_thunk
(
gogo
,
thunk_name
);
// Generate code to call the thunk.
...
...
@@ -2046,15 +2065,14 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
// argument to the thunk.
Expression_list
*
vals
=
new
Expression_list
();
if
(
fntype
->
is_builtin
())
;
else
if
(
!
is_method
)
if
(
!
this
->
is_constant_function
())
vals
->
push_back
(
fn
);
else
if
(
interface_method
!=
NULL
)
if
(
interface_method
!=
NULL
)
vals
->
push_back
(
interface_method
->
expr
());
else
if
(
bound_method
!=
NULL
)
if
(
bound_method
!=
NULL
)
{
vals
->
push_back
(
bound_method
->
method
());
Expression
*
first_arg
=
bound_method
->
first_argument
();
// We always pass a pointer when calling a method.
...
...
@@ -2076,8 +2094,6 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
vals
->
push_back
(
first_arg
);
}
else
go_unreachable
();
if
(
ce
->
args
()
!=
NULL
)
{
...
...
@@ -2152,33 +2168,26 @@ Thunk_statement::build_struct(Function_type* fntype)
Call_expression
*
ce
=
this
->
call_
->
call_expression
();
Expression
*
fn
=
ce
->
fn
();
if
(
!
this
->
is_constant_function
())
{
// The function to call.
fields
->
push_back
(
Struct_field
(
Typed_identifier
(
"fn"
,
fntype
,
location
)));
}
// If this thunk statement calls a method on an interface, we pass
// the interface object to the thunk.
Interface_field_reference_expression
*
interface_method
=
fn
->
interface_field_reference_expression
();
if
(
interface_method
!=
NULL
)
{
// If this thunk statement calls a method on an interface, we
// pass the interface object to the thunk.
Typed_identifier
tid
(
Thunk_statement
::
thunk_field_fn
,
interface_method
->
expr
()
->
type
(),
Typed_identifier
tid
(
"object"
,
interface_method
->
expr
()
->
type
(),
location
);
fields
->
push_back
(
Struct_field
(
tid
));
}
else
if
(
!
fntype
->
is_builtin
())
{
// The function to call.
Typed_identifier
tid
(
Go_statement
::
thunk_field_fn
,
fntype
,
location
);
fields
->
push_back
(
Struct_field
(
tid
));
}
else
if
(
ce
->
is_recover_call
())
{
// The predeclared recover function has no argument. However,
// we add an argument when building recover thunks. Handle that
// here.
fields
->
push_back
(
Struct_field
(
Typed_identifier
(
"can_recover"
,
Type
::
lookup_bool_type
(),
location
)));
}
// If this is a method call, pass down the expression we are
// calling.
if
(
fn
->
bound_method_expression
()
!=
NULL
)
{
go_assert
(
fntype
->
is_method
());
...
...
@@ -2186,11 +2195,19 @@ Thunk_statement::build_struct(Function_type* fntype)
// We always pass the receiver as a pointer.
if
(
rtype
->
points_to
()
==
NULL
)
rtype
=
Type
::
make_pointer_type
(
rtype
);
Typed_identifier
tid
(
Thunk_statement
::
thunk_field_receiver
,
rtype
,
location
);
Typed_identifier
tid
(
"receiver"
,
rtype
,
location
);
fields
->
push_back
(
Struct_field
(
tid
));
}
// The predeclared recover function has no argument. However, we
// add an argument when building recover thunks. Handle that here.
if
(
ce
->
is_recover_call
())
{
fields
->
push_back
(
Struct_field
(
Typed_identifier
(
"can_recover"
,
Type
::
lookup_bool_type
(),
location
)));
}
const
Expression_list
*
args
=
ce
->
args
();
if
(
args
!=
NULL
)
{
...
...
@@ -2213,8 +2230,7 @@ Thunk_statement::build_struct(Function_type* fntype)
// artificial, function.
void
Thunk_statement
::
build_thunk
(
Gogo
*
gogo
,
const
std
::
string
&
thunk_name
,
Function_type
*
fntype
)
Thunk_statement
::
build_thunk
(
Gogo
*
gogo
,
const
std
::
string
&
thunk_name
)
{
source_location
location
=
this
->
location
();
...
...
@@ -2307,37 +2323,37 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
Expression
*
func_to_call
;
unsigned
int
next_index
;
if
(
!
fntype
->
is_builti
n
())
if
(
this
->
is_constant_functio
n
())
{
func_to_call
=
Expression
::
make_field_reference
(
thunk_parameter
,
0
,
location
);
next_index
=
1
;
func_to_call
=
ce
->
fn
();
next_index
=
0
;
}
else
{
go_assert
(
bound_method
==
NULL
&&
interface_method
==
NULL
);
func_to_call
=
ce
->
fn
(
);
next_index
=
0
;
func_to_call
=
Expression
::
make_field_reference
(
thunk_parameter
,
0
,
location
);
next_index
=
1
;
}
if
(
bound_method
!=
NULL
)
{
Expression
*
r
=
Expression
::
make_field_reference
(
thunk_parameter
,
1
,
go_assert
(
next_index
==
0
);
Expression
*
r
=
Expression
::
make_field_reference
(
thunk_parameter
,
0
,
location
);
// The main program passes in a function pointer from the
// interface expression, so here we can make a bound method in
// all cases.
func_to_call
=
Expression
::
make_bound_method
(
r
,
func_to_call
,
func_to_call
=
Expression
::
make_bound_method
(
r
,
bound_method
->
method
(),
location
);
next_index
=
2
;
next_index
=
1
;
}
else
if
(
interface_method
!=
NULL
)
{
// The main program passes the interface object.
go_assert
(
next_index
==
0
);
Expression
*
r
=
Expression
::
make_field_reference
(
thunk_parameter
,
0
,
location
);
const
std
::
string
&
name
(
interface_method
->
name
());
func_to_call
=
Expression
::
make_interface_field_reference
(
func_to_call
,
name
,
func_to_call
=
Expression
::
make_interface_field_reference
(
r
,
name
,
location
);
next_index
=
1
;
}
Expression_list
*
call_params
=
new
Expression_list
();
...
...
gcc/go/gofrontend/statements.h
View file @
48ab8ba6
...
...
@@ -906,21 +906,17 @@ class Thunk_statement : public Statement
bool
is_simple
(
Function_type
*
)
const
;
// Return whether the thunk function is a constant.
bool
is_constant_function
()
const
;
// Build the struct to use for a complex case.
Struct_type
*
build_struct
(
Function_type
*
fntype
);
// Build the thunk.
void
build_thunk
(
Gogo
*
,
const
std
::
string
&
,
Function_type
*
fntype
);
// The field name used in the thunk structure for the function
// pointer.
static
const
char
*
const
thunk_field_fn
;
// The field name used in the thunk structure for the receiver, if
// there is one.
static
const
char
*
const
thunk_field_receiver
;
build_thunk
(
Gogo
*
,
const
std
::
string
&
);
// Set the name to use for thunk field N.
void
...
...
gcc/go/gofrontend/types.cc
View file @
48ab8ba6
...
...
@@ -6085,10 +6085,7 @@ Method::bind_method(Expression* expr, source_location location) const
// the child class.
return
this
->
do_bind_method
(
expr
,
location
);
}
Expression
*
func
=
Expression
::
make_func_reference
(
this
->
stub_
,
NULL
,
location
);
return
Expression
::
make_bound_method
(
expr
,
func
,
location
);
return
Expression
::
make_bound_method
(
expr
,
this
->
stub_
,
location
);
}
// Return the named object associated with a method. This may only be
...
...
@@ -6130,9 +6127,8 @@ Named_method::do_receiver_location() const
Expression
*
Named_method
::
do_bind_method
(
Expression
*
expr
,
source_location
location
)
const
{
Expression
*
func
=
Expression
::
make_func_reference
(
this
->
named_object_
,
NULL
,
location
);
Bound_method_expression
*
bme
=
Expression
::
make_bound_method
(
expr
,
func
,
Named_object
*
no
=
this
->
named_object_
;
Bound_method_expression
*
bme
=
Expression
::
make_bound_method
(
expr
,
no
,
location
);
// If this is not a local method, and it does not use a stub, then
// the real method expects a different type. We need to cast the
...
...
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