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