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
3137991d
Commit
3137991d
authored
Mar 24, 2011
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Tuple receives indicate whether channel is closed.
From-SVN: r171380
parent
4908b0bf
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
309 additions
and
143 deletions
+309
-143
gcc/go/gofrontend/gogo-tree.cc
+1
-1
gcc/go/gofrontend/gogo.cc
+10
-1
gcc/go/gofrontend/gogo.h
+4
-0
gcc/go/gofrontend/parse.cc
+138
-38
gcc/go/gofrontend/parse.h
+4
-2
gcc/go/gofrontend/statements.cc
+78
-41
gcc/go/gofrontend/statements.h
+44
-45
libgo/runtime/chan.goc
+4
-10
libgo/runtime/channel.h
+4
-1
libgo/runtime/go-rec-big.c
+4
-2
libgo/runtime/go-rec-small.c
+18
-2
No files found.
gcc/go/gofrontend/gogo-tree.cc
View file @
3137991d
...
...
@@ -3057,7 +3057,7 @@ Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
location
,
"__go_receive_big"
,
3
,
void
_type_node
,
boolean
_type_node
,
ptr_type_node
,
channel
,
ptr_type_node
,
...
...
gcc/go/gofrontend/gogo.cc
View file @
3137991d
...
...
@@ -1257,7 +1257,7 @@ Lower_parse_tree::statement(Block* block, size_t* pindex, Statement* sorig)
Statement
*
s
=
sorig
;
while
(
true
)
{
Statement
*
snew
=
s
->
lower
(
this
->
gogo_
,
block
);
Statement
*
snew
=
s
->
lower
(
this
->
gogo_
,
this
->
function_
,
block
);
if
(
snew
==
s
)
break
;
s
=
snew
;
...
...
@@ -1305,6 +1305,15 @@ Gogo::lower_parse_tree()
this
->
traverse
(
&
lower_parse_tree
);
}
// Lower a block.
void
Gogo
::
lower_block
(
Named_object
*
function
,
Block
*
block
)
{
Lower_parse_tree
lower_parse_tree
(
this
,
function
);
block
->
traverse
(
&
lower_parse_tree
);
}
// Lower an expression.
void
...
...
gcc/go/gofrontend/gogo.h
View file @
3137991d
...
...
@@ -348,6 +348,10 @@ class Gogo
void
lower_parse_tree
();
// Lower all the statements in a block.
void
lower_block
(
Named_object
*
function
,
Block
*
);
// Lower an expression.
void
lower_expression
(
Named_object
*
function
,
Expression
**
);
...
...
gcc/go/gofrontend/parse.cc
View file @
3137991d
...
...
@@ -4179,10 +4179,12 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
bool
is_send
=
false
;
Expression
*
channel
=
NULL
;
Expression
*
val
=
NULL
;
Expression
*
closed
=
NULL
;
std
::
string
varname
;
std
::
string
closedname
;
bool
is_default
=
false
;
bool
got_case
=
this
->
comm_case
(
&
is_send
,
&
channel
,
&
val
,
&
varname
,
&
is_default
);
bool
got_case
=
this
->
comm_case
(
&
is_send
,
&
channel
,
&
val
,
&
closed
,
&
varname
,
&
closedname
,
&
is_default
);
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_COLON
))
this
->
advance_token
();
...
...
@@ -4191,6 +4193,7 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
Block
*
statements
=
NULL
;
Named_object
*
var
=
NULL
;
Named_object
*
closedvar
=
NULL
;
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_SEMICOLON
))
this
->
advance_token
();
else
if
(
this
->
statement_list_may_start_here
())
...
...
@@ -4206,6 +4209,14 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
var
=
this
->
gogo_
->
add_variable
(
varname
,
v
);
}
if
(
!
closedname
.
empty
())
{
// FIXME: LOCATION is slightly wrong here.
Variable
*
v
=
new
Variable
(
Type
::
lookup_bool_type
(),
NULL
,
false
,
false
,
false
,
location
);
closedvar
=
this
->
gogo_
->
add_variable
(
closedname
,
v
);
}
this
->
statement_list
();
statements
=
this
->
gogo_
->
finish_block
(
this
->
location
());
}
...
...
@@ -4221,7 +4232,8 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
}
if
(
got_case
)
clauses
->
add
(
is_send
,
channel
,
val
,
var
,
is_default
,
statements
,
location
);
clauses
->
add
(
is_send
,
channel
,
val
,
closed
,
var
,
closedvar
,
is_default
,
statements
,
location
);
else
if
(
statements
!=
NULL
)
{
// Add the statements to make sure that any names they define
...
...
@@ -4234,7 +4246,8 @@ Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
bool
Parse
::
comm_case
(
bool
*
is_send
,
Expression
**
channel
,
Expression
**
val
,
std
::
string
*
varname
,
bool
*
is_default
)
Expression
**
closed
,
std
::
string
*
varname
,
std
::
string
*
closedname
,
bool
*
is_default
)
{
const
Token
*
token
=
this
->
peek_token
();
if
(
token
->
is_keyword
(
KEYWORD_DEFAULT
))
...
...
@@ -4245,7 +4258,8 @@ Parse::comm_case(bool* is_send, Expression** channel, Expression** val,
else
if
(
token
->
is_keyword
(
KEYWORD_CASE
))
{
this
->
advance_token
();
if
(
!
this
->
send_or_recv_expr
(
is_send
,
channel
,
val
,
varname
))
if
(
!
this
->
send_or_recv_stmt
(
is_send
,
channel
,
val
,
closed
,
varname
,
closedname
))
return
false
;
}
else
...
...
@@ -4259,74 +4273,160 @@ Parse::comm_case(bool* is_send, Expression** channel, Expression** val,
return
true
;
}
// RecvExpr = [ Expression ( "=" | ":=" ) ] "<-" Expression .
// RecvStmt = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr .
// RecvExpr = Expression .
bool
Parse
::
send_or_recv_expr
(
bool
*
is_send
,
Expression
**
channel
,
Expression
**
val
,
std
::
string
*
varname
)
Parse
::
send_or_recv_stmt
(
bool
*
is_send
,
Expression
**
channel
,
Expression
**
val
,
Expression
**
closed
,
std
::
string
*
varname
,
std
::
string
*
closedname
)
{
const
Token
*
token
=
this
->
peek_token
();
source_location
location
=
token
->
location
();
bool
saw_comma
=
false
;
bool
closed_is_id
=
false
;
if
(
token
->
is_identifier
())
{
Gogo
*
gogo
=
this
->
gogo_
;
std
::
string
recv_var
=
token
->
identifier
();
bool
is_var_exported
=
token
->
is_identifier_exported
();
if
(
!
this
->
advance_token
()
->
is_op
(
OPERATOR_COLONEQ
))
this
->
unget_token
(
Token
::
make_identifier_token
(
recv_var
,
is_var_exported
,
location
));
else
bool
is_rv_exported
=
token
->
is_identifier_exported
();
source_location
recv_var_loc
=
token
->
location
();
token
=
this
->
advance_token
();
if
(
token
->
is_op
(
OPERATOR_COLONEQ
))
{
// case rv := <-c:
if
(
!
this
->
advance_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
error_at
(
this
->
location
(),
"expected %<<-%>"
);
return
false
;
}
if
(
recv_var
==
"_"
)
{
error_at
(
recv_var_loc
,
"no new variables on left side of %<:=%>"
);
recv_var
=
"blank"
;
}
*
is_send
=
false
;
*
varname
=
this
->
gogo_
->
pack_hidden_name
(
recv_var
,
is_var
_exported
);
*
varname
=
gogo
->
pack_hidden_name
(
recv_var
,
is_rv
_exported
);
this
->
advance_token
();
*
channel
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
return
true
;
}
else
if
(
token
->
is_op
(
OPERATOR_COMMA
))
{
token
=
this
->
advance_token
();
if
(
token
->
is_identifier
())
{
std
::
string
recv_closed
=
token
->
identifier
();
bool
is_rc_exported
=
token
->
is_identifier_exported
();
source_location
recv_closed_loc
=
token
->
location
();
closed_is_id
=
true
;
token
=
this
->
advance_token
();
if
(
token
->
is_op
(
OPERATOR_COLONEQ
))
{
// case rv, rc := <-c:
if
(
!
this
->
advance_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
error_at
(
this
->
location
(),
"expected %<<-%>"
);
return
false
;
}
if
(
recv_var
==
"_"
&&
recv_closed
==
"_"
)
{
error_at
(
recv_var_loc
,
"no new variables on left side of %<:=%>"
);
recv_var
=
"blank"
;
}
*
is_send
=
false
;
if
(
recv_var
!=
"_"
)
*
varname
=
gogo
->
pack_hidden_name
(
recv_var
,
is_rv_exported
);
if
(
recv_closed
!=
"_"
)
*
closedname
=
gogo
->
pack_hidden_name
(
recv_closed
,
is_rc_exported
);
this
->
advance_token
();
*
channel
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
return
true
;
}
this
->
unget_token
(
Token
::
make_identifier_token
(
recv_closed
,
is_rc_exported
,
recv_closed_loc
));
}
*
val
=
this
->
id_to_expression
(
gogo
->
pack_hidden_name
(
recv_var
,
is_rv_exported
),
recv_var_loc
);
saw_comma
=
true
;
}
else
this
->
unget_token
(
Token
::
make_identifier_token
(
recv_var
,
is_rv_exported
,
recv_var_loc
));
}
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_CHANOP
))
// If SAW_COMMA is false, then we are looking at the start of the
// send or receive expression. If SAW_COMMA is true, then *VAL is
// set and we just read a comma.
if
(
!
saw_comma
&&
this
->
peek_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
// case <-c:
*
is_send
=
false
;
this
->
advance_token
();
*
channel
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
return
true
;
}
else
{
Expression
*
left
=
this
->
expression
(
PRECEDENCE_NORMAL
,
true
,
true
,
NULL
);
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_EQ
))
Expression
*
e
=
this
->
expression
(
PRECEDENCE_NORMAL
,
true
,
true
,
NULL
);
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_EQ
))
{
if
(
!
this
->
advance_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
if
(
!
this
->
advance_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
error_at
(
this
->
location
(),
"missing %<<-%>"
);
return
false
;
}
*
is_send
=
false
;
*
val
=
left
;
this
->
advance_token
();
*
channel
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
error_at
(
this
->
location
(),
"missing %<<-%>"
);
return
false
;
}
else
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_CHANOP
))
*
is_send
=
false
;
this
->
advance_token
();
*
channel
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
if
(
saw_comma
)
{
*
is_send
=
true
;
*
channel
=
this
->
verify_not_sink
(
left
);
this
->
advance_token
();
*
val
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
)
;
// case v, e = <-c:
// *VAL is already set.
if
(
!
e
->
is_sink_expression
())
*
closed
=
e
;
}
else
{
error_at
(
this
->
location
(),
"expected %<<-%> or %<=%>"
);
return
false
;
// case v = <-c:
if
(
!
e
->
is_sink_expression
())
*
val
=
e
;
}
return
true
;
}
return
true
;
if
(
saw_comma
)
{
if
(
closed_is_id
)
error_at
(
this
->
location
(),
"expected %<=%> or %<:=%>"
);
else
error_at
(
this
->
location
(),
"expected %<=%>"
);
return
false
;
}
if
(
this
->
peek_token
()
->
is_op
(
OPERATOR_CHANOP
))
{
// case c <- v:
*
is_send
=
true
;
*
channel
=
this
->
verify_not_sink
(
e
);
this
->
advance_token
();
*
val
=
this
->
expression
(
PRECEDENCE_NORMAL
,
false
,
true
,
NULL
);
return
true
;
}
error_at
(
this
->
location
(),
"expected %<<-%> or %<=%>"
);
return
false
;
}
// ForStat = "for" [ Condition | ForClause | RangeClause ] Block .
...
...
gcc/go/gofrontend/parse.h
View file @
3137991d
...
...
@@ -246,8 +246,10 @@ class Parse
void
type_switch_case
(
std
::
vector
<
Type
*>*
,
bool
*
);
void
select_stat
(
const
Label
*
);
void
comm_clause
(
Select_clauses
*
,
bool
*
saw_default
);
bool
comm_case
(
bool
*
,
Expression
**
,
Expression
**
,
std
::
string
*
,
bool
*
);
bool
send_or_recv_expr
(
bool
*
,
Expression
**
,
Expression
**
,
std
::
string
*
);
bool
comm_case
(
bool
*
,
Expression
**
,
Expression
**
,
Expression
**
,
std
::
string
*
,
std
::
string
*
,
bool
*
);
bool
send_or_recv_stmt
(
bool
*
,
Expression
**
,
Expression
**
,
Expression
**
,
std
::
string
*
,
std
::
string
*
);
void
for_stat
(
const
Label
*
);
void
for_clause
(
Expression
**
,
Block
**
);
void
range_clause_decl
(
const
Typed_identifier_list
*
,
Range_clause
*
);
...
...
gcc/go/gofrontend/statements.cc
View file @
3137991d
This diff is collapsed.
Click to expand it.
gcc/go/gofrontend/statements.h
View file @
3137991d
...
...
@@ -162,7 +162,7 @@ class Statement
// Make an assignment from a nonblocking receive to a pair of
// variables.
static
Statement
*
make_tuple_receive_assignment
(
Expression
*
val
,
Expression
*
success
,
make_tuple_receive_assignment
(
Expression
*
val
,
Expression
*
closed
,
Expression
*
channel
,
source_location
);
// Make an assignment from a type guard to a pair of variables.
...
...
@@ -284,11 +284,11 @@ class Statement
// Lower a statement. This is called immediately after parsing to
// simplify statements for further processing. It returns the same
// Statement or a new one.
BLOCK is the block
containing this
// statement.
// Statement or a new one.
FUNCTION is the function
containing this
// statement.
BLOCK is the block containing this statement.
Statement
*
lower
(
Gogo
*
gogo
,
Block
*
block
)
{
return
this
->
do_lower
(
gogo
,
block
);
}
lower
(
Gogo
*
gogo
,
Named_object
*
function
,
Block
*
block
)
{
return
this
->
do_lower
(
gogo
,
function
,
block
);
}
// Set type information for unnamed constants.
void
...
...
@@ -381,7 +381,7 @@ class Statement
// Implemented by the child class: lower this statement to a simpler
// one.
virtual
Statement
*
do_lower
(
Gogo
*
,
Block
*
)
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
)
{
return
this
;
}
// Implemented by child class: set type information for unnamed
...
...
@@ -574,7 +574,7 @@ class Return_statement : public Statement
do_traverse_assignments
(
Traverse_assignments
*
);
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
void
do_determine_types
();
...
...
@@ -649,17 +649,22 @@ class Select_clauses
// Add a new clause. IS_SEND is true if this is a send clause,
// false for a receive clause. For a send clause CHANNEL is the
// channel and VAL is the value to send. For a receive clause
// CHANNEL is the channel and VAL is either NULL or a Var_expression
// for the variable to set; if VAL is NULL, VAR may be a variable
// which is initialized with the received value. IS_DEFAULT is true
// if this is the default clause. STATEMENTS is the list of
// statements to execute.
// CHANNEL is the channel, VAL is either NULL or a Var_expression
// for the variable to set, and CLOSED is either NULL or a
// Var_expression to set to whether the channel is closed. If VAL
// is NULL, VAR may be a variable to be initialized with the
// received value, and CLOSEDVAR ma be a variable to be initialized
// with whether the channel is closed. IS_DEFAULT is true if this
// is the default clause. STATEMENTS is the list of statements to
// execute.
void
add
(
bool
is_send
,
Expression
*
channel
,
Expression
*
val
,
Named_object
*
var
,
bool
is_default
,
Block
*
statements
,
source_location
location
)
add
(
bool
is_send
,
Expression
*
channel
,
Expression
*
val
,
Expression
*
closed
,
Named_object
*
var
,
Named_object
*
closedvar
,
bool
is_default
,
Block
*
statements
,
source_location
location
)
{
this
->
clauses_
.
push_back
(
Select_clause
(
is_send
,
channel
,
val
,
var
,
is_default
,
statements
,
location
));
this
->
clauses_
.
push_back
(
Select_clause
(
is_send
,
channel
,
val
,
closed
,
var
,
closedvar
,
is_default
,
statements
,
location
));
}
// Traverse the select clauses.
...
...
@@ -668,7 +673,7 @@ class Select_clauses
// Lower statements.
void
lower
(
Block
*
);
lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
// Determine types.
void
...
...
@@ -689,16 +694,18 @@ class Select_clauses
{
public
:
Select_clause
()
:
channel_
(
NULL
),
val_
(
NULL
),
var_
(
NULL
),
statements_
(
NULL
),
is_send_
(
false
),
is_default_
(
false
)
:
channel_
(
NULL
),
val_
(
NULL
),
closed_
(
NULL
),
var_
(
NULL
),
closedvar_
(
NULL
),
statements_
(
NULL
),
is_send_
(
false
),
is_default_
(
false
)
{
}
Select_clause
(
bool
is_send
,
Expression
*
channel
,
Expression
*
val
,
Named_object
*
var
,
bool
is_default
,
Block
*
statements
,
Expression
*
closed
,
Named_object
*
var
,
Named_object
*
closedvar
,
bool
is_default
,
Block
*
statements
,
source_location
location
)
:
channel_
(
channel
),
val_
(
val
),
var_
(
var
),
statements_
(
statements
),
location_
(
location
),
is_send_
(
is_send
),
is_default_
(
is_default
),
is_lowered_
(
false
)
:
channel_
(
channel
),
val_
(
val
),
closed_
(
closed
),
var_
(
var
),
closedvar_
(
closedvar
),
statements_
(
statements
),
location_
(
location
),
is_
send_
(
is_send
),
is_default_
(
is_default
),
is_
lowered_
(
false
)
{
gcc_assert
(
is_default
?
channel
==
NULL
:
channel
!=
NULL
);
}
// Traverse the select clause.
...
...
@@ -707,7 +714,7 @@ class Select_clauses
// Lower statements.
void
lower
(
Block
*
);
lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
// Determine types.
void
...
...
@@ -724,20 +731,6 @@ class Select_clauses
channel
()
const
{
return
this
->
channel_
;
}
// Return the value. This will return NULL for the default
// clause, or for a receive clause for which no value was given.
Expression
*
val
()
const
{
return
this
->
val_
;
}
// Return the variable to set when a receive clause is also a
// variable definition (v := <- ch). This will return NULL for
// the default case, or for a send clause, or for a receive clause
// which does not define a variable.
Named_object
*
var
()
const
{
return
this
->
var_
;
}
// Return true for a send, false for a receive.
bool
is_send
()
const
...
...
@@ -768,10 +761,16 @@ class Select_clauses
private
:
// The channel.
Expression
*
channel_
;
// The value to send or the
variable to set
.
// The value to send or the
lvalue to receive into
.
Expression
*
val_
;
// The variable to initialize, for "case a := <- ch".
// The lvalue to set to whether the channel is closed on a
// receive.
Expression
*
closed_
;
// The variable to initialize, for "case a := <-ch".
Named_object
*
var_
;
// The variable to initialize to whether the channel is closed,
// for "case a, c := <-ch".
Named_object
*
closedvar_
;
// The statements to execute.
Block
*
statements_
;
// The location of this clause.
...
...
@@ -821,7 +820,7 @@ class Select_statement : public Statement
{
return
this
->
clauses_
->
traverse
(
traverse
);
}
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
void
do_determine_types
()
...
...
@@ -1008,7 +1007,7 @@ class For_statement : public Statement
{
gcc_unreachable
();
}
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
tree
do_get_tree
(
Translate_context
*
)
...
...
@@ -1066,7 +1065,7 @@ class For_range_statement : public Statement
{
gcc_unreachable
();
}
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
tree
do_get_tree
(
Translate_context
*
)
...
...
@@ -1290,7 +1289,7 @@ class Switch_statement : public Statement
do_traverse
(
Traverse
*
);
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
tree
do_get_tree
(
Translate_context
*
)
...
...
@@ -1436,7 +1435,7 @@ class Type_switch_statement : public Statement
do_traverse
(
Traverse
*
);
Statement
*
do_lower
(
Gogo
*
,
Block
*
);
do_lower
(
Gogo
*
,
Named_object
*
,
Block
*
);
tree
do_get_tree
(
Translate_context
*
)
...
...
libgo/runtime/chan.goc
View file @
3137991d
...
...
@@ -12,28 +12,22 @@ typedef struct __go_channel chan;
/*
Do
a
nonblocking
channel
receive
.
*/
func
chanrecv2
(
c
*
chan
,
val
*
byte
)
(
pres
bool
)
{
func
chanrecv2
(
c
*
chan
,
val
*
byte
)
(
received
bool
)
{
if
(
c
->
element_size
>
8
)
{
return
__go_receive_
nonblocking_big
(
c
,
val
);
return
__go_receive_
big
(
c
,
val
,
0
);
}
else
{
struct
__go_receive_nonblocking_small
rs
;
union
{
char
b
[
8
];
uint64_t
v
;
}
u
;
rs
=
__go_receive_nonblocking_small
(
c
);
if
(
!rs.__success) {
__builtin_memset
(
val
,
0
,
c
->
element_size
);
return
0
;
}
u
.
v
=
rs
.
__val
;
u
.
v
=
__go_receive_small_closed
(
c
,
0
,
&
received
);
#
ifndef
WORDS_BIGENDIAN
__builtin_memcpy
(
val
,
u
.
b
,
c
->
element_size
);
#
else
__builtin_memcpy
(
val
,
u
.
b
+
8
-
c
->
element_size
,
c
->
element_size
);
#
endif
return
1
;
return
received
;
}
}
libgo/runtime/channel.h
View file @
3137991d
...
...
@@ -112,6 +112,9 @@ extern int __go_receive_nonblocking_acquire (struct __go_channel *);
extern
uint64_t
__go_receive_small
(
struct
__go_channel
*
,
_Bool
);
extern
uint64_t
__go_receive_small_closed
(
struct
__go_channel
*
,
_Bool
,
_Bool
*
);
extern
void
__go_receive_release
(
struct
__go_channel
*
);
struct
__go_receive_nonblocking_small
...
...
@@ -123,7 +126,7 @@ struct __go_receive_nonblocking_small
extern
struct
__go_receive_nonblocking_small
__go_receive_nonblocking_small
(
struct
__go_channel
*
);
extern
void
__go_receive_big
(
struct
__go_channel
*
,
void
*
,
_Bool
);
extern
_Bool
__go_receive_big
(
struct
__go_channel
*
,
void
*
,
_Bool
);
extern
_Bool
__go_receive_nonblocking_big
(
struct
__go_channel
*
,
void
*
);
...
...
libgo/runtime/go-rec-big.c
View file @
3137991d
...
...
@@ -9,7 +9,7 @@
#include "go-panic.h"
#include "channel.h"
void
_Bool
__go_receive_big
(
struct
__go_channel
*
channel
,
void
*
val
,
_Bool
for_select
)
{
size_t
alloc_size
;
...
...
@@ -24,11 +24,13 @@ __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
if
(
!
__go_receive_acquire
(
channel
,
for_select
))
{
__builtin_memset
(
val
,
0
,
channel
->
element_size
);
return
;
return
0
;
}
offset
=
channel
->
next_fetch
*
alloc_size
;
__builtin_memcpy
(
val
,
&
channel
->
data
[
offset
],
channel
->
element_size
);
__go_receive_release
(
channel
);
return
1
;
}
libgo/runtime/go-rec-small.c
View file @
3137991d
...
...
@@ -263,7 +263,8 @@ __go_unlock_and_notify_selects (struct __go_channel *channel)
/* Receive something 64 bits or smaller on a channel. */
uint64_t
__go_receive_small
(
struct
__go_channel
*
channel
,
_Bool
for_select
)
__go_receive_small_closed
(
struct
__go_channel
*
channel
,
_Bool
for_select
,
_Bool
*
received
)
{
uint64_t
ret
;
...
...
@@ -273,11 +274,26 @@ __go_receive_small (struct __go_channel *channel, _Bool for_select)
__go_assert
(
channel
->
element_size
<=
sizeof
(
uint64_t
));
if
(
!
__go_receive_acquire
(
channel
,
for_select
))
return
0
;
{
if
(
received
!=
NULL
)
*
received
=
0
;
return
0
;
}
ret
=
channel
->
data
[
channel
->
next_fetch
];
__go_receive_release
(
channel
);
if
(
received
!=
NULL
)
*
received
=
1
;
return
ret
;
}
/* Called by the compiler. */
uint64_t
__go_receive_small
(
struct
__go_channel
*
channel
,
_Bool
for_select
)
{
return
__go_receive_small_closed
(
channel
,
for_select
,
NULL
);
}
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