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
58c55a32
Commit
58c55a32
authored
Nov 14, 2013
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
compiler: Use backend interface for comparisons.
From-SVN: r204827
parent
1726bd6e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
110 additions
and
149 deletions
+110
-149
gcc/go/gofrontend/expressions.cc
+105
-146
gcc/go/gofrontend/expressions.h
+5
-3
No files found.
gcc/go/gofrontend/expressions.cc
View file @
58c55a32
...
...
@@ -5321,7 +5321,7 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
}
}
// Lower struct
and array
comparisons.
// Lower struct
, array, and some interface
comparisons.
if
(
op
==
OPERATOR_EQEQ
||
op
==
OPERATOR_NOTEQ
)
{
if
(
left
->
type
()
->
struct_type
()
!=
NULL
)
...
...
@@ -5329,6 +5329,11 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
else
if
(
left
->
type
()
->
array_type
()
!=
NULL
&&
!
left
->
type
()
->
is_slice_type
())
return
this
->
lower_array_comparison
(
gogo
,
inserter
);
else
if
((
left
->
type
()
->
interface_type
()
!=
NULL
&&
right
->
type
()
->
interface_type
()
==
NULL
)
||
(
left
->
type
()
->
interface_type
()
==
NULL
&&
right
->
type
()
->
interface_type
()
!=
NULL
))
return
this
->
lower_interface_value_comparison
(
gogo
,
inserter
);
}
return
this
;
...
...
@@ -5457,6 +5462,57 @@ Binary_expression::lower_array_comparison(Gogo* gogo,
return
ret
;
}
// Lower an interface to value comparison.
Expression
*
Binary_expression
::
lower_interface_value_comparison
(
Gogo
*
,
Statement_inserter
*
inserter
)
{
Type
*
left_type
=
this
->
left_
->
type
();
Type
*
right_type
=
this
->
right_
->
type
();
Interface_type
*
ift
;
if
(
left_type
->
interface_type
()
!=
NULL
)
{
ift
=
left_type
->
interface_type
();
if
(
!
ift
->
implements_interface
(
right_type
,
NULL
))
return
this
;
}
else
{
ift
=
right_type
->
interface_type
();
if
(
!
ift
->
implements_interface
(
left_type
,
NULL
))
return
this
;
}
if
(
!
Type
::
are_compatible_for_comparison
(
true
,
left_type
,
right_type
,
NULL
))
return
this
;
Location
loc
=
this
->
location
();
if
(
left_type
->
interface_type
()
==
NULL
&&
left_type
->
points_to
()
==
NULL
&&
!
this
->
left_
->
is_addressable
())
{
Temporary_statement
*
temp
=
Statement
::
make_temporary
(
left_type
,
NULL
,
loc
);
inserter
->
insert
(
temp
);
this
->
left_
=
Expression
::
make_set_and_use_temporary
(
temp
,
this
->
left_
,
loc
);
}
if
(
right_type
->
interface_type
()
==
NULL
&&
right_type
->
points_to
()
==
NULL
&&
!
this
->
right_
->
is_addressable
())
{
Temporary_statement
*
temp
=
Statement
::
make_temporary
(
right_type
,
NULL
,
loc
);
inserter
->
insert
(
temp
);
this
->
right_
=
Expression
::
make_set_and_use_temporary
(
temp
,
this
->
right_
,
loc
);
}
return
this
;
}
// Lower a struct or array comparison to a call to memcmp.
Expression
*
...
...
@@ -5919,8 +5975,7 @@ Binary_expression::do_get_tree(Translate_context* context)
case
OPERATOR_GT
:
case
OPERATOR_GE
:
return
Expression
::
comparison_tree
(
context
,
this
->
type_
,
this
->
op_
,
this
->
left_
->
type
(),
left
,
this
->
right_
->
type
(),
right
,
this
->
left_
,
this
->
right_
,
this
->
location
());
case
OPERATOR_OROR
:
...
...
@@ -6417,12 +6472,16 @@ Expression::make_binary(Operator op, Expression* left, Expression* right,
tree
Expression
::
comparison_tree
(
Translate_context
*
context
,
Type
*
result_type
,
Operator
op
,
Type
*
left_type
,
tree
left_tree
,
Type
*
right_type
,
tree
right_tree
,
Location
location
)
Operator
op
,
Expression
*
left_expr
,
Expression
*
right_expr
,
Location
location
)
{
Type
*
int_type
=
Type
::
lookup_integer_type
(
"int"
);
tree
int_type_tree
=
type_to_tree
(
int_type
->
get_backend
(
context
->
gogo
()));
Type
*
left_type
=
left_expr
->
type
();
Type
*
right_type
=
right_expr
->
type
();
mpz_t
zval
;
mpz_init_set_ui
(
zval
,
0UL
);
Expression
*
zexpr
=
Expression
::
make_integer
(
&
zval
,
NULL
,
location
);
mpz_clear
(
zval
);
enum
tree_code
code
;
switch
(
op
)
...
...
@@ -6449,21 +6508,17 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
go_unreachable
();
}
// FIXME: Computing the tree here means it will be computed multiple times,
// which is wasteful. This is a temporary modification until all tree code
// here can be replaced with frontend expressions.
tree
left_tree
=
left_expr
->
get_tree
(
context
);
tree
right_tree
=
right_expr
->
get_tree
(
context
);
if
(
left_type
->
is_string_type
()
&&
right_type
->
is_string_type
())
{
Type
*
st
=
Type
::
make_string_type
();
tree
string_type
=
type_to_tree
(
st
->
get_backend
(
context
->
gogo
()));
static
tree
string_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
string_compare_decl
,
location
,
"__go_strcmp"
,
2
,
int_type_tree
,
string_type
,
left_tree
,
string_type
,
right_tree
);
right_tree
=
build_int_cst_type
(
int_type_tree
,
0
);
Expression
*
strcmp_call
=
Runtime
::
make_call
(
Runtime
::
STRCMP
,
location
,
2
,
left_expr
,
right_expr
);
left_tree
=
strcmp_call
->
get_tree
(
context
);
right_tree
=
zexpr
->
get_tree
(
context
);
}
else
if
((
left_type
->
interface_type
()
!=
NULL
&&
right_type
->
interface_type
()
==
NULL
...
...
@@ -6476,154 +6531,61 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
if
(
left_type
->
interface_type
()
==
NULL
)
{
std
::
swap
(
left_type
,
right_type
);
std
::
swap
(
left_
tree
,
right_tree
);
std
::
swap
(
left_
expr
,
right_expr
);
}
// The right operand is not an interface. We need to take its
// address if it is not a pointer.
tree
make_tmp
;
tree
arg
;
Expression
*
pointer_arg
=
NULL
;
if
(
right_type
->
points_to
()
!=
NULL
)
{
make_tmp
=
NULL_TREE
;
arg
=
right_tree
;
}
else
if
(
TREE_ADDRESSABLE
(
TREE_TYPE
(
right_tree
))
||
(
TREE_CODE
(
right_tree
)
!=
CONST_DECL
&&
DECL_P
(
right_tree
)))
{
make_tmp
=
NULL_TREE
;
arg
=
build_fold_addr_expr_loc
(
location
.
gcc_location
(),
right_tree
);
if
(
DECL_P
(
right_tree
))
TREE_ADDRESSABLE
(
right_tree
)
=
1
;
}
else
{
tree
tmp
=
create_tmp_var
(
TREE_TYPE
(
right_tree
),
get_name
(
right_tree
));
DECL_IGNORED_P
(
tmp
)
=
0
;
DECL_INITIAL
(
tmp
)
=
right_tree
;
TREE_ADDRESSABLE
(
tmp
)
=
1
;
make_tmp
=
build1
(
DECL_EXPR
,
void_type_node
,
tmp
);
SET_EXPR_LOCATION
(
make_tmp
,
location
.
gcc_location
());
arg
=
build_fold_addr_expr_loc
(
location
.
gcc_location
(),
tmp
);
}
arg
=
fold_convert_loc
(
location
.
gcc_location
(),
ptr_type_node
,
arg
);
Bexpression
*
descriptor_bexpr
=
right_type
->
type_descriptor_pointer
(
context
->
gogo
(),
location
);
tree
descriptor
=
expr_to_tree
(
descriptor_bexpr
);
if
(
left_type
->
interface_type
()
->
is_empty
())
{
static
tree
empty_interface_value_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
empty_interface_value_compare_decl
,
location
,
"__go_empty_interface_value_compare"
,
3
,
int_type_tree
,
TREE_TYPE
(
left_tree
),
left_tree
,
TREE_TYPE
(
descriptor
),
descriptor
,
ptr_type_node
,
arg
);
if
(
left_tree
==
error_mark_node
)
return
error_mark_node
;
// This can panic if the type is not comparable.
TREE_NOTHROW
(
empty_interface_value_compare_decl
)
=
0
;
}
pointer_arg
=
right_expr
;
else
{
static
tree
interface_value_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
interface_value_compare_decl
,
location
,
"__go_interface_value_compare"
,
3
,
int_type_tree
,
TREE_TYPE
(
left_tree
),
left_tree
,
TREE_TYPE
(
descriptor
),
descriptor
,
ptr_type_node
,
arg
);
if
(
left_tree
==
error_mark_node
)
return
error_mark_node
;
// This can panic if the type is not comparable.
TREE_NOTHROW
(
interface_value_compare_decl
)
=
0
;
go_assert
(
right_expr
->
is_addressable
());
pointer_arg
=
Expression
::
make_unary
(
OPERATOR_AND
,
right_expr
,
location
);
}
right_tree
=
build_int_cst_type
(
int_type_tree
,
0
);
if
(
make_tmp
!=
NULL_TREE
)
left_tree
=
build2
(
COMPOUND_EXPR
,
TREE_TYPE
(
left_tree
),
make_tmp
,
left_tree
);
Expression
*
descriptor_expr
=
Expression
::
make_type_descriptor
(
right_type
,
location
);
Call_expression
*
iface_valcmp
=
Runtime
::
make_call
((
left_type
->
interface_type
()
->
is_empty
()
?
Runtime
::
EMPTY_INTERFACE_VALUE_COMPARE
:
Runtime
::
INTERFACE_VALUE_COMPARE
),
location
,
3
,
left_expr
,
descriptor_expr
,
pointer_arg
);
left_tree
=
iface_valcmp
->
get_tree
(
context
);
right_tree
=
zexpr
->
get_tree
(
context
);
}
else
if
(
left_type
->
interface_type
()
!=
NULL
&&
right_type
->
interface_type
()
!=
NULL
)
{
Runtime
::
Function
compare_function
;
if
(
left_type
->
interface_type
()
->
is_empty
()
&&
right_type
->
interface_type
()
->
is_empty
())
{
static
tree
empty_interface_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
empty_interface_compare_decl
,
location
,
"__go_empty_interface_compare"
,
2
,
int_type_tree
,
TREE_TYPE
(
left_tree
),
left_tree
,
TREE_TYPE
(
right_tree
),
right_tree
);
if
(
left_tree
==
error_mark_node
)
return
error_mark_node
;
// This can panic if the type is uncomparable.
TREE_NOTHROW
(
empty_interface_compare_decl
)
=
0
;
}
compare_function
=
Runtime
::
EMPTY_INTERFACE_COMPARE
;
else
if
(
!
left_type
->
interface_type
()
->
is_empty
()
&&
!
right_type
->
interface_type
()
->
is_empty
())
{
static
tree
interface_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
interface_compare_decl
,
location
,
"__go_interface_compare"
,
2
,
int_type_tree
,
TREE_TYPE
(
left_tree
),
left_tree
,
TREE_TYPE
(
right_tree
),
right_tree
);
if
(
left_tree
==
error_mark_node
)
return
error_mark_node
;
// This can panic if the type is uncomparable.
TREE_NOTHROW
(
interface_compare_decl
)
=
0
;
}
compare_function
=
Runtime
::
INTERFACE_COMPARE
;
else
{
if
(
left_type
->
interface_type
()
->
is_empty
())
{
go_assert
(
op
==
OPERATOR_EQEQ
||
op
==
OPERATOR_NOTEQ
);
std
::
swap
(
left_type
,
right_type
);
std
::
swap
(
left_
tree
,
right_tree
);
std
::
swap
(
left_
expr
,
right_expr
);
}
go_assert
(
!
left_type
->
interface_type
()
->
is_empty
());
go_assert
(
right_type
->
interface_type
()
->
is_empty
());
static
tree
interface_empty_compare_decl
;
left_tree
=
Gogo
::
call_builtin
(
&
interface_empty_compare_decl
,
location
,
"__go_interface_empty_compare"
,
2
,
int_type_tree
,
TREE_TYPE
(
left_tree
),
left_tree
,
TREE_TYPE
(
right_tree
),
right_tree
);
if
(
left_tree
==
error_mark_node
)
return
error_mark_node
;
// This can panic if the type is uncomparable.
TREE_NOTHROW
(
interface_empty_compare_decl
)
=
0
;
compare_function
=
Runtime
::
INTERFACE_EMPTY_COMPARE
;
}
right_tree
=
build_int_cst_type
(
int_type_tree
,
0
);
Call_expression
*
ifacecmp_call
=
Runtime
::
make_call
(
compare_function
,
location
,
2
,
left_expr
,
right_expr
);
left_tree
=
ifacecmp_call
->
get_tree
(
context
);
right_tree
=
zexpr
->
get_tree
(
context
);
}
if
(
left_type
->
is_nil_type
()
...
...
@@ -11908,14 +11870,11 @@ Interface_field_reference_expression::do_get_tree(Translate_context* context)
// Note that we are evaluating this->expr_ twice, but that is OK
// because in the lowering pass we forced it into a temporary
// variable.
tree
expr_tree
=
this
->
expr_
->
get_tree
(
context
);
tree
nil_check_tree
=
Expression
::
comparison_tree
(
context
,
Type
::
lookup_bool_type
(),
OPERATOR_EQEQ
,
this
->
expr_
->
type
(),
expr_tree
,
Type
::
make_nil_type
(),
null_pointer_node
,
this
->
expr_
,
Expression
::
make_nil
(
loc
),
loc
);
tree
crash
=
context
->
gogo
()
->
runtime_error
(
RUNTIME_ERROR_NIL_DEREFERENCE
,
loc
);
...
...
gcc/go/gofrontend/expressions.h
View file @
58c55a32
...
...
@@ -655,12 +655,11 @@ class Expression
Type
*
rhs_type
,
tree
rhs_tree
,
bool
for_type_guard
,
Location
);
// Return a tree implementing the comparison LHS_
TREE OP RHS_TREE
.
// Return a tree implementing the comparison LHS_
EXPR OP RHS_EXPR
.
// TYPE is the type of both sides.
static
tree
comparison_tree
(
Translate_context
*
,
Type
*
result_type
,
Operator
op
,
Type
*
left_type
,
tree
left_tree
,
Type
*
right_type
,
tree
right_tree
,
Location
);
Expression
*
left_expr
,
Expression
*
right_expr
,
Location
);
// Return the backend expression for the numeric constant VAL.
static
Bexpression
*
...
...
@@ -1306,6 +1305,9 @@ class Binary_expression : public Expression
lower_array_comparison
(
Gogo
*
,
Statement_inserter
*
);
Expression
*
lower_interface_value_comparison
(
Gogo
*
,
Statement_inserter
*
);
Expression
*
lower_compare_to_memcmp
(
Gogo
*
,
Statement_inserter
*
);
Expression
*
...
...
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