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
a6de01a6
Commit
a6de01a6
authored
Apr 15, 2011
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use backend interface for send statement.
From-SVN: r172519
parent
2ba172e0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
112 additions
and
154 deletions
+112
-154
gcc/go/gofrontend/expressions.cc
+10
-0
gcc/go/gofrontend/gogo-tree.cc
+0
-138
gcc/go/gofrontend/gogo.h
+0
-5
gcc/go/gofrontend/statements.cc
+102
-11
No files found.
gcc/go/gofrontend/expressions.cc
View file @
a6de01a6
...
...
@@ -3622,6 +3622,16 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context)
&&
et
->
interface_type
()
->
is_empty
());
use_view_convert
=
true
;
}
else
if
(
t
->
integer_type
()
!=
NULL
)
{
gcc_assert
(
et
->
is_boolean_type
()
||
et
->
integer_type
()
!=
NULL
||
et
->
function_type
()
!=
NULL
||
et
->
points_to
()
!=
NULL
||
et
->
map_type
()
!=
NULL
||
et
->
channel_type
()
!=
NULL
);
return
convert_to_integer
(
type_tree
,
expr_tree
);
}
else
gcc_unreachable
();
...
...
gcc/go/gofrontend/gogo-tree.cc
View file @
a6de01a6
...
...
@@ -2764,144 +2764,6 @@ Gogo::runtime_error(int code, source_location location)
return
ret
;
}
// Send VAL on CHANNEL. If BLOCKING is true, the resulting tree has a
// void type. If BLOCKING is false, the resulting tree has a boolean
// type, and it will evaluate as true if the value was sent. If
// FOR_SELECT is true, this is being done because it was chosen in a
// select statement.
tree
Gogo
::
send_on_channel
(
tree
channel
,
tree
val
,
bool
blocking
,
bool
for_select
,
source_location
location
)
{
if
(
channel
==
error_mark_node
||
val
==
error_mark_node
)
return
error_mark_node
;
if
(
int_size_in_bytes
(
TREE_TYPE
(
val
))
<=
8
&&
!
AGGREGATE_TYPE_P
(
TREE_TYPE
(
val
))
&&
!
FLOAT_TYPE_P
(
TREE_TYPE
(
val
)))
{
val
=
convert_to_integer
(
uint64_type_node
,
val
);
if
(
blocking
)
{
static
tree
send_small_fndecl
;
tree
ret
=
Gogo
::
call_builtin
(
&
send_small_fndecl
,
location
,
"__go_send_small"
,
3
,
void_type_node
,
ptr_type_node
,
channel
,
uint64_type_node
,
val
,
boolean_type_node
,
(
for_select
?
boolean_true_node
:
boolean_false_node
));
if
(
ret
==
error_mark_node
)
return
error_mark_node
;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW
(
send_small_fndecl
)
=
0
;
return
ret
;
}
else
{
gcc_assert
(
!
for_select
);
static
tree
send_nonblocking_small_fndecl
;
tree
ret
=
Gogo
::
call_builtin
(
&
send_nonblocking_small_fndecl
,
location
,
"__go_send_nonblocking_small"
,
2
,
boolean_type_node
,
ptr_type_node
,
channel
,
uint64_type_node
,
val
);
if
(
ret
==
error_mark_node
)
return
error_mark_node
;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW
(
send_nonblocking_small_fndecl
)
=
0
;
return
ret
;
}
}
else
{
tree
make_tmp
;
if
(
TREE_ADDRESSABLE
(
TREE_TYPE
(
val
))
||
TREE_CODE
(
val
)
==
VAR_DECL
)
{
make_tmp
=
NULL_TREE
;
val
=
build_fold_addr_expr
(
val
);
if
(
DECL_P
(
val
))
TREE_ADDRESSABLE
(
val
)
=
1
;
}
else
{
tree
tmp
=
create_tmp_var
(
TREE_TYPE
(
val
),
get_name
(
val
));
DECL_IGNORED_P
(
tmp
)
=
0
;
DECL_INITIAL
(
tmp
)
=
val
;
TREE_ADDRESSABLE
(
tmp
)
=
1
;
make_tmp
=
build1
(
DECL_EXPR
,
void_type_node
,
tmp
);
SET_EXPR_LOCATION
(
make_tmp
,
location
);
val
=
build_fold_addr_expr
(
tmp
);
}
val
=
fold_convert
(
ptr_type_node
,
val
);
tree
call
;
if
(
blocking
)
{
static
tree
send_big_fndecl
;
call
=
Gogo
::
call_builtin
(
&
send_big_fndecl
,
location
,
"__go_send_big"
,
3
,
void_type_node
,
ptr_type_node
,
channel
,
ptr_type_node
,
val
,
boolean_type_node
,
(
for_select
?
boolean_true_node
:
boolean_false_node
));
if
(
call
==
error_mark_node
)
return
error_mark_node
;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW
(
send_big_fndecl
)
=
0
;
}
else
{
gcc_assert
(
!
for_select
);
static
tree
send_nonblocking_big_fndecl
;
call
=
Gogo
::
call_builtin
(
&
send_nonblocking_big_fndecl
,
location
,
"__go_send_nonblocking_big"
,
2
,
boolean_type_node
,
ptr_type_node
,
channel
,
ptr_type_node
,
val
);
if
(
call
==
error_mark_node
)
return
error_mark_node
;
// This can panic if there are too many operations on a
// closed channel.
TREE_NOTHROW
(
send_nonblocking_big_fndecl
)
=
0
;
}
if
(
make_tmp
==
NULL_TREE
)
return
call
;
else
{
tree
ret
=
build2
(
COMPOUND_EXPR
,
TREE_TYPE
(
call
),
make_tmp
,
call
);
SET_EXPR_LOCATION
(
ret
,
location
);
return
ret
;
}
}
}
// Return a tree for receiving a value of type TYPE_TREE on CHANNEL.
// This does a blocking receive and returns the value read from the
// channel. If FOR_SELECT is true, this is being done because it was
...
...
gcc/go/gofrontend/gogo.h
View file @
a6de01a6
...
...
@@ -526,11 +526,6 @@ class Gogo
tree
go_string_constant_tree
(
const
std
::
string
&
);
// Send a value on a channel.
static
tree
send_on_channel
(
tree
channel
,
tree
val
,
bool
blocking
,
bool
for_select
,
source_location
);
// Receive a value from a channel.
static
tree
receive_from_channel
(
tree
type_tree
,
tree
channel
,
bool
for_select
,
...
...
gcc/go/gofrontend/statements.cc
View file @
a6de01a6
...
...
@@ -3779,18 +3779,109 @@ Send_statement::do_check_types(Gogo*)
tree
Send_statement
::
do_get_tree
(
Translate_context
*
context
)
{
tree
channel
=
this
->
channel_
->
get_tree
(
context
);
tree
val
=
this
->
val_
->
get_tree
(
context
);
if
(
channel
==
error_mark_node
||
val
==
error_mark_node
)
return
error_mark_node
;
source_location
loc
=
this
->
location
();
Channel_type
*
channel_type
=
this
->
channel_
->
type
()
->
channel_type
();
val
=
Expression
::
convert_for_assignment
(
context
,
channel_type
->
element_type
(),
this
->
val_
->
type
(),
val
,
this
->
location
());
return
Gogo
::
send_on_channel
(
channel
,
val
,
true
,
this
->
for_select_
,
this
->
location
());
Type
*
element_type
=
channel_type
->
element_type
();
Expression
*
val
=
Expression
::
make_cast
(
element_type
,
this
->
val_
,
loc
);
bool
is_small
;
bool
can_take_address
;
switch
(
element_type
->
base
()
->
classification
())
{
case
Type
:
:
TYPE_BOOLEAN
:
case
Type
:
:
TYPE_INTEGER
:
case
Type
:
:
TYPE_FUNCTION
:
case
Type
:
:
TYPE_POINTER
:
case
Type
:
:
TYPE_MAP
:
case
Type
:
:
TYPE_CHANNEL
:
is_small
=
true
;
can_take_address
=
false
;
break
;
case
Type
:
:
TYPE_FLOAT
:
case
Type
:
:
TYPE_COMPLEX
:
case
Type
:
:
TYPE_STRING
:
case
Type
:
:
TYPE_INTERFACE
:
is_small
=
false
;
can_take_address
=
false
;
break
;
case
Type
:
:
TYPE_STRUCT
:
is_small
=
false
;
can_take_address
=
true
;
break
;
case
Type
:
:
TYPE_ARRAY
:
is_small
=
false
;
can_take_address
=
!
element_type
->
is_open_array_type
();
break
;
default
:
case
Type
:
:
TYPE_ERROR
:
case
Type
:
:
TYPE_VOID
:
case
Type
:
:
TYPE_SINK
:
case
Type
:
:
TYPE_NIL
:
case
Type
:
:
TYPE_NAMED
:
case
Type
:
:
TYPE_FORWARD
:
gcc_assert
(
saw_errors
());
return
error_mark_node
;
}
// Only try to take the address of a variable. We have already
// moved variables to the heap, so this should not cause that to
// happen unnecessarily.
if
(
can_take_address
&&
val
->
var_expression
()
==
NULL
&&
val
->
temporary_reference_expression
()
==
NULL
)
can_take_address
=
false
;
Runtime
::
Function
code
;
Bstatement
*
btemp
=
NULL
;
Expression
*
call
;
if
(
is_small
)
{
// Type is small enough to handle as uint64.
code
=
Runtime
::
SEND_SMALL
;
val
=
Expression
::
make_unsafe_cast
(
Type
::
lookup_integer_type
(
"uint64"
),
val
,
loc
);
}
else
if
(
can_take_address
)
{
// Must pass address of value. The function doesn't change the
// value, so just take its address directly.
code
=
Runtime
::
SEND_BIG
;
val
=
Expression
::
make_unary
(
OPERATOR_AND
,
val
,
loc
);
}
else
{
// Must pass address of value, but the value is small enough
// that it might be in registers. Copy value into temporary
// variable to take address.
code
=
Runtime
::
SEND_BIG
;
Temporary_statement
*
temp
=
Statement
::
make_temporary
(
element_type
,
val
,
loc
);
Expression
*
ref
=
Expression
::
make_temporary_reference
(
temp
,
loc
);
val
=
Expression
::
make_unary
(
OPERATOR_AND
,
ref
,
loc
);
btemp
=
tree_to_stat
(
temp
->
get_tree
(
context
));
}
call
=
Runtime
::
make_call
(
code
,
loc
,
3
,
this
->
channel_
,
val
,
Expression
::
make_boolean
(
this
->
for_select_
,
loc
));
context
->
gogo
()
->
lower_expression
(
context
->
function
(),
&
call
);
Bexpression
*
bcall
=
tree_to_expr
(
call
->
get_tree
(
context
));
Bstatement
*
s
=
context
->
backend
()
->
expression_statement
(
bcall
);
if
(
btemp
==
NULL
)
return
stat_to_tree
(
s
);
else
{
std
::
vector
<
Bstatement
*>
stats
(
2
);
stats
[
0
]
=
btemp
;
stats
[
1
]
=
s
;
return
stat_to_tree
(
context
->
backend
()
->
statement_list
(
stats
));
}
}
// Make a send statement.
...
...
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