summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-02 10:40:41 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-02 10:40:41 +0000
commita634a685a892b0ef270b2ce7454290f4d83cc715 (patch)
tree46788ae87e00f56ecc4ee43355d56869b303f7a9
parent52a88d12a0ae93c5e474f2c897876b0dc3f2e1e1 (diff)
downloadgcc-a634a685a892b0ef270b2ce7454290f4d83cc715.tar.gz
2011-12-02 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 181902 using svnmerge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@181903 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.MELT4
-rw-r--r--gcc/ChangeLog84
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in4
-rw-r--r--gcc/cfgexpand.c6
-rw-r--r--gcc/cgraph.c2
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/cgraphunit.c2
-rw-r--r--gcc/config/sh/sh.c4
-rw-r--r--gcc/config/sh/sh.h3
-rw-r--r--gcc/config/sh/sh.md42
-rw-r--r--gcc/coverage.c18
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/call.c19
-rw-r--r--gcc/cp/pt.c13
-rw-r--r--gcc/cp/tree.c1
-rw-r--r--gcc/fortran/ChangeLog18
-rw-r--r--gcc/fortran/misc.c8
-rw-r--r--gcc/fortran/module.c160
-rw-r--r--gcc/gimple.c30
-rw-r--r--gcc/gimple.h14
-rw-r--r--gcc/go/gofrontend/export.cc1
-rw-r--r--gcc/go/gofrontend/export.h3
-rw-r--r--gcc/go/gofrontend/expressions.cc9
-rw-r--r--gcc/go/gofrontend/expressions.h9
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc27
-rw-r--r--gcc/go/gofrontend/gogo.h7
-rw-r--r--gcc/go/gofrontend/import.cc1
-rw-r--r--gcc/go/gofrontend/parse.cc2
-rw-r--r--gcc/go/gofrontend/runtime.cc16
-rw-r--r--gcc/go/gofrontend/runtime.def50
-rw-r--r--gcc/go/gofrontend/runtime.h5
-rw-r--r--gcc/go/gofrontend/statements.cc544
-rw-r--r--gcc/go/gofrontend/statements.h83
-rw-r--r--gcc/ipa-inline.c18
-rw-r--r--gcc/loop-unroll.c11
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/lto/lto-lang.c18
-rw-r--r--gcc/testsuite/ChangeLog40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist61.C9
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-12.C21
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-8.C14
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-9.C17
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcovpart-12b.C5
-rw-r--r--gcc/testsuite/g++.dg/inherit/crash3.C11
-rw-r--r--gcc/testsuite/g++.dg/opt/pr51014.C16
-rw-r--r--gcc/testsuite/g++.dg/template/error47.C9
-rw-r--r--gcc/testsuite/g++.dg/torture/pr51198.C29
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr51246.c14
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-13.c4
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-16.c12
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-17.c12
-rw-r--r--gcc/testsuite/lib/gcov.exp47
-rw-r--r--gcc/tree-predcom.c14
-rw-r--r--gcc/tree-ssa-dce.c20
-rw-r--r--gcc/tree-ssa-live.c12
-rw-r--r--gcc/tree-vect-patterns.c2
-rw-r--r--gcc/tree-vrp.c60
-rw-r--r--gcc/tree.c3
-rw-r--r--libgo/Makefile.am16
-rw-r--r--libgo/Makefile.in182
-rw-r--r--libgo/runtime/chan.c1248
-rw-r--r--libgo/runtime/chan.goc57
-rw-r--r--libgo/runtime/channel.h152
-rw-r--r--libgo/runtime/go-chan-cap.c41
-rw-r--r--libgo/runtime/go-chan-len.c41
-rw-r--r--libgo/runtime/go-close.c42
-rw-r--r--libgo/runtime/go-new-channel.c70
-rw-r--r--libgo/runtime/go-rec-big.c43
-rw-r--r--libgo/runtime/go-rec-nb-big.c46
-rw-r--r--libgo/runtime/go-rec-nb-small.c123
-rw-r--r--libgo/runtime/go-rec-small.c304
-rw-r--r--libgo/runtime/go-reflect-chan.c200
-rw-r--r--libgo/runtime/go-select.c758
-rw-r--r--libgo/runtime/go-send-big.c34
-rw-r--r--libgo/runtime/go-send-nb-big.c33
-rw-r--r--libgo/runtime/go-send-nb-small.c107
-rw-r--r--libgo/runtime/go-send-small.c159
-rw-r--r--libgo/runtime/go-signal.c4
-rw-r--r--libgo/runtime/runtime.h11
-rw-r--r--libgo/runtime/thread.c24
82 files changed, 2251 insertions, 3082 deletions
diff --git a/ChangeLog.MELT b/ChangeLog.MELT
index 7e066f0f450..061b238c568 100644
--- a/ChangeLog.MELT
+++ b/ChangeLog.MELT
@@ -1,4 +1,8 @@
+2011-12-02 Basile Starynkevitch <basile@starynkevitch.net>
+
+ MELT branch merged with trunk rev 181902 using svnmerge
+
2011-12-01 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 181872 using svnmerge
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index addee392384..0a15c038954 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,87 @@
+2011-12-01 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR target/50814.
+ * config/sh/sh.c (expand_ashiftrt): Handle TARGET_SH2A same as
+ TARGET_SH3.
+ (shl_sext_kind): Likewise.
+ * config/sh/sh.h (SH_DYNAMIC_SHIFT_COST): Likewise.
+ * config/sh/sh.md (ashlsi3_sh2a, ashrsi3_sh2a, lshrsi3_sh2a):
+ Remove.
+ (ashlsi3_std): Handle TARGET_SH2A same as TARGET_SH3.
+ (ashlsi3): Likewise.
+ (ashrsi3_d): Likewise.
+ (lshrsi3_d): Likewise.
+ (lshrsi3): Likewise.
+
+2011-12-01 Diego Novillo <dnovillo@google.com>
+
+ PR bootstrap/51346
+ * ipa-inline.c (can_inline_edge_p): If the edge E has a
+ statement, use the statement's inline indicator instead
+ of E's.
+ Remove consistency check.
+
+2011-12-01 Diego Novillo <dnovillo@google.com>
+
+ PR bootstrap/51346
+ Revert
+
+ 2011-11-29 Diego Novillo <dnovillo@google.com>
+
+ * gimple.c (gimple_call_set_cannot_inline): Move from gimple.h.
+ Update field call_stmt_cannot_inline_p from call
+ graph edge, if needed.
+ * gimple.h (gimple_call_set_cannot_inline): Move to gimple.c.
+
+2011-12-01 Nathan Sidwell <nathan@acm.org>
+
+ PR gcov-profile/51113
+ * coverage.c (build_var): Keep coverage variables static.
+
+2011-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51356
+ * tree-vect-patterns.c (vect_recog_bool_pattern): Give up if
+ vectype doesn't have VECTOR_MODE_P.
+
+ PR debug/50317
+ * tree-ssa-dce.c (remove_dead_stmt): Add a debug stmt when removing
+ as unnecessary a store to a variable with gimple reg type.
+ * tree-ssa-live.c (remove_unused_locals): Clear TREE_ADDRESSABLE bit
+ on local unreferenced variables.
+ * cfgexpand.c (expand_gimple_basic_block): Don't emit DEBUG_INSNs
+ for !target_for_debug_bind variables.
+
+2011-12-01 Patrick Marlier <patrick.marlier@gmail.com>
+
+ PR middle-end/51273
+ * cgraph.h (cgraph_call_node_duplication_hooks): Declare.
+ * cgraph.c (cgraph_call_node_duplication_hooks): Make global.
+ * cgraphunit.c (cgraph_copy_node_for_versioning): Call it.
+
+2011-12-01 Andrew Pinski <apinski@cavium.com>
+
+ PR lto/51198
+ * tree.c (free_lang_data_in_decl): Clear FIELD_DECL's
+ DECL_INITIAL also.
+
+2011-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51246
+ * tree-predcom.c (replace_ref_with): Handle also clobber on the
+ rhs.
+
+ PR rtl-optimization/51014
+ * loop-unroll.c (apply_opt_in_copies): Ignore label DEBUG_INSNs
+ both from bb and orig_bb.
+
+2011-12-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ PR tree-optimization/50802
+ * tree-vrp.c (simplify_conversion_using_ranges): Rewrite test
+ considering what happens to ranges during sign changes and/or
+ intermediate narrowing conversions.
+
2011-11-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR middle-end/50283
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 1678f2f93ab..c30346e372a 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20111201
+20111202
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 77fd4bf15d1..9a8a4ed3fab 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/51201
+ * gcc-interface/Make-lang.in: Initialize RTS_DIR with = instead of :=.
+
2011-11-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* s-taprop-tru64.adb (Create_Task): Use Unrestricted_Access.
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 44d75154779..e375796ec8e 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -118,7 +118,7 @@ ifeq ($(build), $(host))
# put the host RTS dir first in the PATH to hide the default runtime
# files that are among the sources
- RTS_DIR:=$(strip $(subst \,/,$(shell gnatls -v | grep adalib )))
+ RTS_DIR=$(strip $(subst \,/,$(shell gnatls -v | grep adalib )))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
@@ -153,7 +153,7 @@ else
else
# This is a canadian cross. We should use a toolchain running on the
# build platform and targeting the host platform.
- RTS_DIR:=$(strip $(subst \,/,$(shell $(GNATLS_FOR_HOST) -v | grep adalib )))
+ RTS_DIR=$(strip $(subst \,/,$(shell $(GNATLS_FOR_HOST) -v | grep adalib )))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
$(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 2a82b032f5d..e5a7a392eb4 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3903,6 +3903,11 @@ expand_gimple_basic_block (basic_block bb)
rtx val;
enum machine_mode mode;
+ if (TREE_CODE (var) != DEBUG_EXPR_DECL
+ && TREE_CODE (var) != LABEL_DECL
+ && !target_for_debug_bind (var))
+ goto delink_debug_stmt;
+
if (gimple_debug_bind_has_value_p (stmt))
value = gimple_debug_bind_get_value (stmt);
else
@@ -3932,6 +3937,7 @@ expand_gimple_basic_block (basic_block bb)
PAT_VAR_LOCATION_LOC (val) = (rtx)value;
}
+ delink_debug_stmt:
/* In order not to generate too many debug temporaries,
we delink all uses of debug statements we already expanded.
Therefore debug statements between definition and real
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 44a950ca743..ac516abefba 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -412,7 +412,7 @@ cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *entry)
}
/* Call all node duplication hooks. */
-static void
+void
cgraph_call_node_duplication_hooks (struct cgraph_node *node1,
struct cgraph_node *node2)
{
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 834d3d4a443..0efce347261 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -513,6 +513,8 @@ struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
int, bool, VEC(cgraph_edge_p,heap) *,
bool);
struct cgraph_node *cgraph_create_function_alias (tree, tree);
+void cgraph_call_node_duplication_hooks (struct cgraph_node *node1,
+ struct cgraph_node *node2);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 40bcf8fc9ef..251b5554725 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2318,6 +2318,8 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
cgraph_redirect_edge_callee (e, new_version);
}
+ cgraph_call_node_duplication_hooks (old_version, new_version);
+
return new_version;
}
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 870c39f2602..b9834fb5c9f 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -3266,7 +3266,7 @@ expand_ashiftrt (rtx *operands)
char func[18];
int value;
- if (TARGET_SH3)
+ if (TARGET_SH3 || TARGET_SH2A)
{
if (!CONST_INT_P (operands[2]))
{
@@ -3715,7 +3715,7 @@ shl_sext_kind (rtx left_rtx, rtx size_rtx, int *costp)
}
}
}
- if (TARGET_SH3)
+ if (TARGET_SH3 || TARGET_SH2A)
{
/* Try to use a dynamic shift. */
cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST;
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 8ab1f10e31e..f873b9d72a3 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2394,7 +2394,8 @@ extern int current_function_interrupt;
#define ACCUMULATE_OUTGOING_ARGS TARGET_ACCUMULATE_OUTGOING_ARGS
#define SH_DYNAMIC_SHIFT_COST \
- (TARGET_HARD_SH4 ? 1 : TARGET_SH3 ? (optimize_size ? 1 : 2) : 20)
+ (TARGET_HARD_SH4 ? 1 \
+ : (TARGET_SH3 || TARGET_SH2A) ? (optimize_size ? 1 : 2) : 20)
#define NUM_MODES_FOR_MODE_SWITCHING { FP_MODE_NONE }
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index ce660185dd3..b63c8572d74 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -1,6 +1,6 @@
;;- Machine description for Renesas / SuperH SH.
;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; Free Software Foundation, Inc.
;; Contributed by Steve Chamberlain (sac@cygnus.com).
;; Improved by Jim Wilson (wilson@cygnus.com).
@@ -3568,15 +3568,6 @@ label:
;;
;; shift left
-(define_insn "ashlsi3_sh2a"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
- (match_operand:SI 2 "arith_reg_operand" "r")))]
- "TARGET_SH2A"
- "shad %2,%0"
- [(set_attr "type" "arith")
- (set_attr "length" "4")])
-
;; This pattern is used by init_expmed for computing the costs of shift
;; insns.
@@ -3585,14 +3576,14 @@ label:
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
(match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
(clobber (match_scratch:SI 3 "=X,X,X,&r"))]
- "TARGET_SH3
+ "(TARGET_SH3 || TARGET_SH2A)
|| (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
"@
shld %2,%0
add %0,%0
shll%O2 %0
#"
- "TARGET_SH3
+ "(TARGET_SH3 || TARGET_SH2A)
&& reload_completed
&& CONST_INT_P (operands[2])
&& ! satisfies_constraint_P27 (operands[2])"
@@ -3671,7 +3662,7 @@ label:
if (CONST_INT_P (operands[2])
&& sh_dynamicalize_shift_p (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
- if (TARGET_SH3)
+ if (TARGET_SH3 || TARGET_SH2A)
{
emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
DONE;
@@ -3728,15 +3719,6 @@ label:
; arithmetic shift right
;
-(define_insn "ashrsi3_sh2a"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
- (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
- "TARGET_SH2A"
- "shad %2,%0"
- [(set_attr "type" "dyn_shift")
- (set_attr "length" "4")])
-
(define_insn "ashrsi3_k"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
@@ -3831,7 +3813,7 @@ label:
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
- "TARGET_SH3"
+ "TARGET_SH3 || TARGET_SH2A"
"shad %2,%0"
[(set_attr "type" "dyn_shift")])
@@ -3879,20 +3861,11 @@ label:
;; logical shift right
-(define_insn "lshrsi3_sh2a"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
- (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
- "TARGET_SH2A"
- "shld %2,%0"
- [(set_attr "type" "dyn_shift")
- (set_attr "length" "4")])
-
(define_insn "lshrsi3_d"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
- "TARGET_SH3"
+ "TARGET_SH3 || TARGET_SH2A"
"shld %2,%0"
[(set_attr "type" "dyn_shift")])
@@ -3973,7 +3946,8 @@ label:
if (CONST_INT_P (operands[2])
&& sh_dynamicalize_shift_p (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
- if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
+ if ((TARGET_SH3 || TARGET_SH2A)
+ && arith_reg_operand (operands[2], GET_MODE (operands[2])))
{
rtx count = copy_to_mode_reg (SImode, operands[2]);
emit_insn (gen_negsi2 (count, count));
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 65ceba22783..23cb2f8cf55 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -657,8 +657,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
}
/* Build a coverage variable of TYPE for function FN_DECL. If COUNTER
- >= 0 it is a counter array, otherwise it is the function structure.
- Propagate appropriate linkage and visibility from the function decl. */
+ >= 0 it is a counter array, otherwise it is the function structure. */
static tree
build_var (tree fn_decl, tree type, int counter)
@@ -675,21 +674,6 @@ build_var (tree fn_decl, tree type, int counter)
TREE_STATIC (var) = 1;
TREE_ADDRESSABLE (var) = 1;
DECL_ALIGN (var) = TYPE_ALIGN (type);
- DECL_WEAK (var) = DECL_WEAK (fn_decl);
- TREE_PUBLIC (var)
- = TREE_PUBLIC (fn_decl) && (counter < 0 || DECL_WEAK (fn_decl));
- if (DECL_ONE_ONLY (fn_decl))
- make_decl_one_only (var, DECL_COMDAT_GROUP (fn_decl));
-
- if (TREE_PUBLIC (var))
- {
- DECL_VISIBILITY (var) = DECL_VISIBILITY (fn_decl);
- DECL_VISIBILITY_SPECIFIED (var)
- = DECL_VISIBILITY_SPECIFIED (fn_decl);
-
- /* Initialize assembler name so we can stream out. */
- DECL_ASSEMBLER_NAME (var);
- }
return var;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 55addacfe46..201f5efb603 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2011-12-01 Jason Merrill <jason@redhat.com>
+
+ * call.c (build_new_method_call_1): Handle aggregate initialization.
+ * tree.c (stabilize_init): Handle CONSTRUCTOR.
+
+2011-12-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51326
+ * call.c (build_user_type_conversion_1): Early return NULL if
+ expr is NULL_TREE.
+
+2011-12-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51367
+ * pt.c (unify_inconsistency): Use either %qT or %qE depending on
+ whether parm is a type or non-type parameter.
+
2011-11-30 Jason Merrill <jason@redhat.com>
PR c++/51009
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ab0654273a3..548a36bf8e5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3373,7 +3373,7 @@ static struct z_candidate *
build_user_type_conversion_1 (tree totype, tree expr, int flags)
{
struct z_candidate *candidates, *cand;
- tree fromtype = TREE_TYPE (expr);
+ tree fromtype;
tree ctors = NULL_TREE;
tree conv_fns = NULL_TREE;
conversion *conv = NULL;
@@ -3382,6 +3382,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
bool any_viable_p;
int convflags;
+ if (!expr)
+ return NULL;
+
+ fromtype = TREE_TYPE (expr);
+
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
constructor calls, as specified in [dcl.init]. */
@@ -7193,6 +7198,7 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
&& CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)))
{
tree init_list = VEC_index (tree, *args, 0);
+ tree init = NULL_TREE;
gcc_assert (VEC_length (tree, *args) == 1
&& !(flags & LOOKUP_ONLYCONVERTING));
@@ -7204,8 +7210,16 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
if (CONSTRUCTOR_NELTS (init_list) == 0
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
&& !processing_template_decl)
+ init = build_value_init (basetype, complain);
+
+ /* If BASETYPE is an aggregate, we need to do aggregate
+ initialization. */
+ else if (CP_AGGREGATE_TYPE_P (basetype))
+ init = digest_init (basetype, init_list, complain);
+
+ if (init)
{
- tree ob, init = build_value_init (basetype, complain);
+ tree ob;
if (integer_zerop (instance_ptr))
return get_target_expr_sfinae (init, complain);
ob = build_fold_indirect_ref (instance_ptr);
@@ -7214,6 +7228,7 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
return init;
}
+ /* Otherwise go ahead with overload resolution. */
add_list_candidates (fns, first_mem_arg, init_list,
basetype, explicit_targs, template_only,
conversion_path, access_binfo, flags, &candidates);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 47250807577..15ef7a0caea 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5501,9 +5501,16 @@ static int
unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
{
if (explain_p)
- inform (input_location,
- " conflicting deductions for parameter %qE (%qE and %qE)",
- parm, first, second);
+ {
+ if (TYPE_P (parm))
+ inform (input_location,
+ " deduced conflicting types for parameter %qT (%qT and %qT)",
+ parm, first, second);
+ else
+ inform (input_location,
+ " deduced conflicting values for non-type parameter "
+ "%qE (%qE and %qE)", parm, first, second);
+ }
return 1;
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d206fd2ec24..8d179d8d2a0 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3337,6 +3337,7 @@ stabilize_init (tree init, tree *initp)
if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != CONSTRUCTOR
&& TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
{
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 170c6fbdeff..3fee56d891f 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,21 @@
+2011-12-01 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * module.c (dt_lower_string): Make static.
+ (dt_upper_string): Likewise.
+
+2011-12-01 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR fortran/25708
+ * module.c (parse_string): Read string into resizable array
+ instead of parsing twice and seeking.
+ (peek_atom): New implementation avoiding seeks.
+ (require_atom): Save and set column and line explicitly for error
+ handling.
+
+2011-12-01 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * misc.c (gfc_open_file): Don't call stat.
+
2011-11-29 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/40958
diff --git a/gcc/fortran/misc.c b/gcc/fortran/misc.c
index 12740478257..05aef9f02ea 100644
--- a/gcc/fortran/misc.c
+++ b/gcc/fortran/misc.c
@@ -58,17 +58,9 @@ gfc_clear_ts (gfc_typespec *ts)
FILE *
gfc_open_file (const char *name)
{
- struct stat statbuf;
-
if (!*name)
return stdin;
- if (stat (name, &statbuf) < 0)
- return NULL;
-
- if (!S_ISREG (statbuf.st_mode))
- return NULL;
-
return fopen (name, "r");
}
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 70f8565c150..1ab08ae2cdf 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -435,7 +435,7 @@ resolve_fixups (fixup_t *f, void *gp)
to convert the symtree name of a derived-type to the symbol name or to
the name of the associated generic function. */
-const char *
+static const char *
dt_lower_string (const char *name)
{
if (name[0] != (char) TOLOWER ((unsigned char) name[0]))
@@ -450,7 +450,7 @@ dt_lower_string (const char *name)
symtree/symbol name of the associated generic function start with a lower-
case character. */
-const char *
+static const char *
dt_upper_string (const char *name)
{
if (name[0] != (char) TOUPPER ((unsigned char) name[0]))
@@ -1069,51 +1069,37 @@ module_unget_char (void)
static void
parse_string (void)
{
- module_locus start;
- int len, c;
- char *p;
-
- get_module_locus (&start);
+ int c;
+ size_t cursz = 30;
+ size_t len = 0;
- len = 0;
+ atom_string = XNEWVEC (char, cursz);
- /* See how long the string is. */
for ( ; ; )
{
c = module_char ();
- if (c == EOF)
- bad_module ("Unexpected end of module in string constant");
- if (c != '\'')
+ if (c == '\'')
{
- len++;
- continue;
+ int c2 = module_char ();
+ if (c2 != '\'')
+ {
+ module_unget_char ();
+ break;
+ }
}
- c = module_char ();
- if (c == '\'')
+ if (len >= cursz)
{
- len++;
- continue;
+ cursz *= 2;
+ atom_string = XRESIZEVEC (char, atom_string, cursz);
}
-
- break;
- }
-
- set_module_locus (&start);
-
- atom_string = p = XCNEWVEC (char, len + 1);
-
- for (; len > 0; len--)
- {
- c = module_char ();
- if (c == '\'')
- module_char (); /* Guaranteed to be another \'. */
- *p++ = c;
+ atom_string[len] = c;
+ len++;
}
- module_char (); /* Terminating \'. */
- *p = '\0'; /* C-style string for debug purposes. */
+ atom_string = XRESIZEVEC (char, atom_string, len + 1);
+ atom_string[len] = '\0'; /* C-style string for debug purposes. */
}
@@ -1279,17 +1265,99 @@ parse_atom (void)
static atom_type
peek_atom (void)
{
- module_locus m;
- atom_type a;
+ int c;
- get_module_locus (&m);
+ do
+ {
+ c = module_char ();
+ }
+ while (c == ' ' || c == '\r' || c == '\n');
+
+ switch (c)
+ {
+ case '(':
+ module_unget_char ();
+ return ATOM_LPAREN;
- a = parse_atom ();
- if (a == ATOM_STRING)
- free (atom_string);
+ case ')':
+ module_unget_char ();
+ return ATOM_RPAREN;
+
+ case '\'':
+ module_unget_char ();
+ return ATOM_STRING;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ module_unget_char ();
+ return ATOM_INTEGER;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'H':
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'R':
+ case 'S':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ module_unget_char ();
+ return ATOM_NAME;
- set_module_locus (&m);
- return a;
+ default:
+ bad_module ("Bad name");
+ }
}
@@ -1299,11 +1367,12 @@ peek_atom (void)
static void
require_atom (atom_type type)
{
- module_locus m;
atom_type t;
const char *p;
+ int column, line;
- get_module_locus (&m);
+ column = module_column;
+ line = module_line;
t = parse_atom ();
if (t != type)
@@ -1329,7 +1398,8 @@ require_atom (atom_type type)
gfc_internal_error ("require_atom(): bad atom type required");
}
- set_module_locus (&m);
+ module_column = column;
+ module_line = line;
bad_module (p);
}
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index d27e94b218c..071c6515b4c 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -5558,34 +5558,4 @@ gimple_asm_clobbers_memory_p (const_gimple stmt)
return false;
}
-
-
-/* Set the inlinable status of GIMPLE_CALL S to INLINABLE_P. */
-
-void
-gimple_call_set_cannot_inline (gimple s, bool inlinable_p)
-{
- bool prev_inlinable_p;
-
- GIMPLE_CHECK (s, GIMPLE_CALL);
-
- prev_inlinable_p = gimple_call_cannot_inline_p (s);
-
- if (inlinable_p)
- s->gsbase.subcode |= GF_CALL_CANNOT_INLINE;
- else
- s->gsbase.subcode &= ~GF_CALL_CANNOT_INLINE;
-
- /* If we have changed the inlinable attribute, and there is a call
- graph edge going out of this statement, update its inlinable
- attribute as well. */
- if (current_function_decl && prev_inlinable_p != inlinable_p)
- {
- struct cgraph_node *n = cgraph_get_node (current_function_decl);
- struct cgraph_edge *e = cgraph_edge (n, s);
- if (e)
- e->call_stmt_cannot_inline_p = inlinable_p;
- }
-}
-
#include "gt-gimple.h"
diff --git a/gcc/gimple.h b/gcc/gimple.h
index df31bf3c23a..8536c70e87e 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1035,7 +1035,6 @@ extern bool walk_stmt_load_store_ops (gimple, void *,
extern bool gimple_ior_addresses_taken (bitmap, gimple);
extern bool gimple_call_builtin_p (gimple, enum built_in_function);
extern bool gimple_asm_clobbers_memory_p (const_gimple);
-extern void gimple_call_set_cannot_inline (gimple, bool);
/* In gimplify.c */
extern tree create_tmp_var_raw (tree, const char *);
@@ -2344,6 +2343,19 @@ gimple_call_tail_p (gimple s)
}
+/* Set the inlinable status of GIMPLE_CALL S to INLINABLE_P. */
+
+static inline void
+gimple_call_set_cannot_inline (gimple s, bool inlinable_p)
+{
+ GIMPLE_CHECK (s, GIMPLE_CALL);
+ if (inlinable_p)
+ s->gsbase.subcode |= GF_CALL_CANNOT_INLINE;
+ else
+ s->gsbase.subcode &= ~GF_CALL_CANNOT_INLINE;
+}
+
+
/* Return true if GIMPLE_CALL S cannot be inlined. */
static inline bool
diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc
index 0832055510c..3fb7089cc7c 100644
--- a/gcc/go/gofrontend/export.cc
+++ b/gcc/go/gofrontend/export.cc
@@ -337,6 +337,7 @@ Export::register_builtin_types(Gogo* gogo)
this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
this->register_builtin_type(gogo, "string", BUILTIN_STRING);
+ this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
}
// Register one builtin type in the export table.
diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h
index 1f8278f419a..a06b549b609 100644
--- a/gcc/go/gofrontend/export.h
+++ b/gcc/go/gofrontend/export.h
@@ -39,8 +39,9 @@ enum Builtin_code
BUILTIN_STRING = -16,
BUILTIN_COMPLEX64 = -17,
BUILTIN_COMPLEX128 = -18,
+ BUILTIN_ERROR = -19,
- SMALLEST_BUILTIN_CODE = -18
+ SMALLEST_BUILTIN_CODE = -19
};
// This class manages exporting Go declarations. It handles the main
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index a2cf33eb67b..a80c82375ce 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -13493,12 +13493,18 @@ Receive_expression::do_check_types(Gogo*)
tree
Receive_expression::do_get_tree(Translate_context* context)
{
+ Location loc = this->location();
+
Channel_type* channel_type = this->channel_->type()->channel_type();
if (channel_type == NULL)
{
go_assert(this->channel_->type()->is_error());
return error_mark_node;
}
+
+ Expression* td = Expression::make_type_descriptor(channel_type, loc);
+ tree td_tree = td->get_tree(context);
+
Type* element_type = channel_type->element_type();
Btype* element_type_btype = element_type->get_backend(context->gogo());
tree element_type_tree = type_to_tree(element_type_btype);
@@ -13507,8 +13513,7 @@ Receive_expression::do_get_tree(Translate_context* context)
if (element_type_tree == error_mark_node || channel == error_mark_node)
return error_mark_node;
- return Gogo::receive_from_channel(element_type_tree, channel,
- this->for_select_, this->location());
+ return Gogo::receive_from_channel(element_type_tree, td_tree, channel, loc);
}
// Dump ast representation for a receive expression.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 74d1281e17c..6da507b57ca 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -1947,7 +1947,7 @@ class Receive_expression : public Expression
public:
Receive_expression(Expression* channel, Location location)
: Expression(EXPRESSION_RECEIVE, location),
- channel_(channel), for_select_(false)
+ channel_(channel)
{ }
// Return the channel.
@@ -1955,11 +1955,6 @@ class Receive_expression : public Expression
channel()
{ return this->channel_; }
- // Note that this is for a select statement.
- void
- set_for_select()
- { this->for_select_ = true; }
-
protected:
int
do_traverse(Traverse* traverse)
@@ -1998,8 +1993,6 @@ class Receive_expression : public Expression
private:
// The channel from which we are receiving.
Expression* channel_;
- // Whether this is for a select statement.
- bool for_select_;
};
#endif // !defined(GO_EXPRESSIONS_H)
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index 0e77f5dcd61..dd66a7f6832 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -2201,13 +2201,12 @@ Gogo::runtime_error(int code, Location location)
}
// 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
-// chosen in a select statement.
+// TYPE_DESCRIPTOR_TREE is the channel's type descriptor. This does a
+// blocking receive and returns the value read from the channel.
tree
-Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
- Location location)
+Gogo::receive_from_channel(tree type_tree, tree type_descriptor_tree,
+ tree channel, Location location)
{
if (type_tree == error_mark_node || channel == error_mark_node)
return error_mark_node;
@@ -2222,12 +2221,10 @@ Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
"__go_receive_small",
2,
uint64_type_node,
+ TREE_TYPE(type_descriptor_tree),
+ type_descriptor_tree,
ptr_type_node,
- channel,
- boolean_type_node,
- (for_select
- ? boolean_true_node
- : boolean_false_node));
+ channel);
if (call == error_mark_node)
return error_mark_node;
// This can panic if there are too many operations on a closed
@@ -2253,15 +2250,13 @@ Gogo::receive_from_channel(tree type_tree, tree channel, bool for_select,
location,
"__go_receive_big",
3,
- boolean_type_node,
+ void_type_node,
+ TREE_TYPE(type_descriptor_tree),
+ type_descriptor_tree,
ptr_type_node,
channel,
ptr_type_node,
- tmpaddr,
- boolean_type_node,
- (for_select
- ? boolean_true_node
- : boolean_false_node));
+ tmpaddr);
if (call == error_mark_node)
return error_mark_node;
// This can panic if there are too many operations on a closed
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 9d3b37ae857..6efce18cfac 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -527,14 +527,9 @@ class Gogo
// Receive a value from a channel.
static tree
- receive_from_channel(tree type_tree, tree channel, bool for_select,
+ receive_from_channel(tree type_tree, tree type_descriptor_tree, tree channel,
Location);
- // Return a tree for receiving an integer on a channel.
- static tree
- receive_as_64bit_integer(tree type, tree channel, bool blocking,
- bool for_select);
-
// Make a trampoline which calls FNADDR passing CLOSURE.
tree
make_trampoline(tree fnaddr, tree closure, Location);
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index d3405c191c9..075109c0c04 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -706,6 +706,7 @@ Import::register_builtin_types(Gogo* gogo)
this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
this->register_builtin_type(gogo, "string", BUILTIN_STRING);
+ this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
}
// Register a single builtin type.
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 62288687662..37a97825bcd 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -1780,7 +1780,6 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
Statement* s = Statement::make_tuple_receive_assignment(val_var,
received_var,
receive->channel(),
- false,
location);
if (!this->gogo_->in_global_scope())
@@ -3769,7 +3768,6 @@ Parse::tuple_assignment(Expression_list* lhs, Range_clause* p_range_clause)
Expression* channel = receive->channel();
Statement* s = Statement::make_tuple_receive_assignment(val, success,
channel,
- false,
location);
this->gogo_->add_statement(s);
}
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 42f1e787a8f..bffefbb0513 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -54,8 +54,6 @@ enum Runtime_function_type
RFT_MAPITER,
// Go type chan any, C type struct __go_channel *.
RFT_CHAN,
- // Go type *chan any, C type struct __go_channel **.
- RFT_CHANPTR,
// Go type non-empty interface, C type struct __go_interface.
RFT_IFACE,
// Go type interface{}, C type struct __go_empty_interface.
@@ -148,10 +146,6 @@ runtime_function_type(Runtime_function_type bft)
t = Type::make_channel_type(true, true, Type::make_void_type());
break;
- case RFT_CHANPTR:
- t = Type::make_pointer_type(runtime_function_type(RFT_CHAN));
- break;
-
case RFT_IFACE:
{
Typed_identifier_list* methods = new Typed_identifier_list();
@@ -223,7 +217,6 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_SLICE:
case RFT_MAP:
case RFT_CHAN:
- case RFT_CHANPTR:
case RFT_IFACE:
case RFT_EFACE:
return Expression::make_unsafe_cast(runtime_function_type(bft), e, loc);
@@ -393,12 +386,3 @@ Runtime::map_iteration_type()
return Type::make_array_type(runtime_function_type(RFT_POINTER), iexpr);
}
-
-// Return the type used to pass a list of general channels to the
-// select runtime function.
-
-Type*
-Runtime::chanptr_type()
-{
- return runtime_function_type(RFT_CHANPTR);
-}
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index d742e5b0c79..fe842c93b9b 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -121,31 +121,44 @@ DEF_GO_RUNTIME(CHAN_LEN, "__go_chan_len", P1(CHAN), R1(INT))
DEF_GO_RUNTIME(CHAN_CAP, "__go_chan_cap", P1(CHAN), R1(INT))
// Send a small value on a channel.
-DEF_GO_RUNTIME(SEND_SMALL, "__go_send_small", P3(CHAN, UINT64, BOOL), R0())
-
-// Send a small value on a channel without blocking.
-DEF_GO_RUNTIME(SEND_NONBLOCKING_SMALL, "__go_send_nonblocking_small",
- P2(CHAN, UINT64), R1(BOOL))
+DEF_GO_RUNTIME(SEND_SMALL, "__go_send_small", P3(TYPE, CHAN, UINT64), R0())
// Send a big value on a channel.
-DEF_GO_RUNTIME(SEND_BIG, "__go_send_big", P3(CHAN, POINTER, BOOL), R0())
-
-// Send a big value on a channel without blocking.
-DEF_GO_RUNTIME(SEND_NONBLOCKING_BIG, "__go_send_nonblocking_big",
- P2(CHAN, POINTER), R1(BOOL))
+DEF_GO_RUNTIME(SEND_BIG, "__go_send_big", P3(TYPE, CHAN, POINTER), R0())
// Receive a small value from a channel.
-DEF_GO_RUNTIME(RECEIVE_SMALL, "__go_receive_small", P2(CHAN, BOOL), R1(UINT64))
+DEF_GO_RUNTIME(RECEIVE_SMALL, "__go_receive_small", P2(TYPE, CHAN), R1(UINT64))
// Receive a big value from a channel.
-DEF_GO_RUNTIME(RECEIVE_BIG, "__go_receive_big", P3(CHAN, POINTER, BOOL),
- R1(BOOL))
+DEF_GO_RUNTIME(RECEIVE_BIG, "__go_receive_big", P3(TYPE, CHAN, POINTER), R0())
// Receive a value from a channel returning whether it is closed.
-DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P2(CHAN, POINTER), R1(BOOL))
+DEF_GO_RUNTIME(CHANRECV2, "runtime.chanrecv2", P3(TYPE, CHAN, POINTER),
+ R1(BOOL))
+
+
+// Start building a select statement.
+DEF_GO_RUNTIME(NEWSELECT, "runtime.newselect", P1(INT), R1(POINTER))
-// Receive a value from a channel returning whether it is closed, for select.
-DEF_GO_RUNTIME(CHANRECV3, "runtime.chanrecv3", P2(CHAN, POINTER), R1(BOOL))
+// Add a default clause to a select statement.
+DEF_GO_RUNTIME(SELECTDEFAULT, "runtime.selectdefault", P2(POINTER, INT), R0())
+
+// Add a send clause to a select statement.
+DEF_GO_RUNTIME(SELECTSEND, "runtime.selectsend",
+ P4(POINTER, CHAN, POINTER, INT), R0())
+
+// Add a receive clause to a select statement, for a clause which does
+// not check whether the channel is closed.
+DEF_GO_RUNTIME(SELECTRECV, "runtime.selectrecv",
+ P4(POINTER, CHAN, POINTER, INT), R0())
+
+// Add a receive clause to a select statement, for a clause which does
+// check whether the channel is closed.
+DEF_GO_RUNTIME(SELECTRECV2, "runtime.selectrecv2",
+ P5(POINTER, CHAN, POINTER, BOOLPTR, INT), R0())
+
+// Run a select, returning the index of the selected clause.
+DEF_GO_RUNTIME(SELECTGO, "runtime.selectgo", P1(POINTER), R1(INT))
// Panic.
@@ -213,11 +226,6 @@ DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
DEF_GO_RUNTIME(DEFER, "__go_defer", P3(BOOLPTR, FUNC_PTR, POINTER), R0())
-// Run a select statement.
-DEF_GO_RUNTIME(SELECT, "__go_select", P4(UINTPTR, BOOL, CHANPTR, BOOLPTR),
- R1(UINTPTR))
-
-
// Convert an empty interface to an empty interface, returning ok.
DEF_GO_RUNTIME(IFACEE2E2, "runtime.ifaceE2E2", P1(EFACE), R2(EFACE, BOOL))
diff --git a/gcc/go/gofrontend/runtime.h b/gcc/go/gofrontend/runtime.h
index 3cd40348cbe..be5dcbe25d0 100644
--- a/gcc/go/gofrontend/runtime.h
+++ b/gcc/go/gofrontend/runtime.h
@@ -43,11 +43,6 @@ class Runtime
static Type*
map_iteration_type();
- // Return the type used to pass a list of general channels to the
- // select runtime function.
- static Type*
- chanptr_type();
-
private:
static Named_object*
runtime_declaration(Function);
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 835a0cca239..964b394c3bd 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -1329,10 +1329,9 @@ class Tuple_receive_assignment_statement : public Statement
{
public:
Tuple_receive_assignment_statement(Expression* val, Expression* closed,
- Expression* channel, bool for_select,
- Location location)
+ Expression* channel, Location location)
: Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
- val_(val), closed_(closed), channel_(channel), for_select_(for_select)
+ val_(val), closed_(closed), channel_(channel)
{ }
protected:
@@ -1360,8 +1359,6 @@ class Tuple_receive_assignment_statement : public Statement
Expression* closed_;
// The channel on which we receive the value.
Expression* channel_;
- // Whether this is for a select statement.
- bool for_select_;
};
// Traversal.
@@ -1414,14 +1411,14 @@ Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
b->add_statement(closed_temp);
- // closed_temp = chanrecv[23](channel, &val_temp)
+ // closed_temp = chanrecv2(type, channel, &val_temp)
+ Expression* td = Expression::make_type_descriptor(this->channel_->type(),
+ loc);
Temporary_reference_expression* ref =
Expression::make_temporary_reference(val_temp, loc);
Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
- Expression* call = Runtime::make_call((this->for_select_
- ? Runtime::CHANRECV3
- : Runtime::CHANRECV2),
- loc, 2, this->channel_, p2);
+ Expression* call = Runtime::make_call(Runtime::CHANRECV2,
+ loc, 3, td, this->channel_, p2);
ref = Expression::make_temporary_reference(closed_temp, loc);
ref->set_is_lvalue();
Statement* s = Statement::make_assignment(ref, call, loc);
@@ -1460,11 +1457,10 @@ Tuple_receive_assignment_statement::do_dump_statement(
Statement*
Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
Expression* channel,
- bool for_select,
Location location)
{
return new Tuple_receive_assignment_statement(val, closed, channel,
- for_select, location);
+ location);
}
// An assignment to a pair of values from a type guard. This is a
@@ -4391,9 +4387,11 @@ Send_statement::do_get_backend(Translate_context* context)
&& val->temporary_reference_expression() == NULL)
can_take_address = false;
+ Expression* td = Expression::make_type_descriptor(this->channel_->type(),
+ loc);
+
Runtime::Function code;
Bstatement* btemp = NULL;
- Expression* call;
if (is_small)
{
// Type is small enough to handle as uint64.
@@ -4421,8 +4419,7 @@ Send_statement::do_get_backend(Translate_context* context)
btemp = temp->get_backend(context);
}
- call = Runtime::make_call(code, loc, 3, this->channel_, val,
- Expression::make_boolean(this->for_select_, loc));
+ Expression* call = Runtime::make_call(code, loc, 3, td, this->channel_, val);
context->gogo()->lower_expression(context->function(), NULL, &call);
Bexpression* bcall = tree_to_expr(call->get_tree(context));
@@ -4490,134 +4487,178 @@ Select_clauses::Select_clause::traverse(Traverse* traverse)
return TRAVERSE_CONTINUE;
}
-// Lowering. Here we pull out the channel and the send values, to
-// enforce the order of evaluation. We also add explicit send and
-// receive statements to the clauses.
+// Lowering. We call a function to register this clause, and arrange
+// to set any variables in any receive clause.
void
Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
- Block* b)
+ Block* b, Temporary_statement* sel)
{
+ Location loc = this->location_;
+
+ Expression* selref = Expression::make_temporary_reference(sel, loc);
+
+ mpz_t ival;
+ mpz_init_set_ui(ival, this->index_);
+ Expression* index_expr = Expression::make_integer(&ival, NULL, loc);
+ mpz_clear(ival);
+
if (this->is_default_)
{
go_assert(this->channel_ == NULL && this->val_ == NULL);
+ this->lower_default(b, selref, index_expr);
this->is_lowered_ = true;
return;
}
- Location loc = this->location_;
-
// Evaluate the channel before the select statement.
Temporary_statement* channel_temp = Statement::make_temporary(NULL,
this->channel_,
loc);
b->add_statement(channel_temp);
- this->channel_ = Expression::make_temporary_reference(channel_temp, loc);
-
- // If this is a send clause, evaluate the value to send before the
- // select statement.
- Temporary_statement* val_temp = NULL;
- if (this->is_send_ && !this->val_->is_constant())
- {
- val_temp = Statement::make_temporary(NULL, this->val_, loc);
- b->add_statement(val_temp);
- }
+ Expression* chanref = Expression::make_temporary_reference(channel_temp,
+ loc);
- // Add the send or receive before the rest of the statements if any.
- Block *init = new Block(b, loc);
- Expression* ref = Expression::make_temporary_reference(channel_temp, loc);
if (this->is_send_)
- {
- Expression* ref2;
- if (val_temp == NULL)
- ref2 = this->val_;
- else
- ref2 = Expression::make_temporary_reference(val_temp, loc);
- Send_statement* send = Statement::make_send_statement(ref, ref2, loc);
- send->set_for_select();
- init->add_statement(send);
- }
- else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
- {
- go_assert(this->var_ == NULL && this->closedvar_ == NULL);
- if (this->val_ == NULL)
- this->val_ = Expression::make_sink(loc);
- Statement* s = Statement::make_tuple_receive_assignment(this->val_,
- this->closed_,
- ref, true, loc);
- init->add_statement(s);
- }
- else if (this->closedvar_ != NULL)
- {
- go_assert(this->val_ == NULL);
- Expression* val;
- if (this->var_ == NULL)
- val = Expression::make_sink(loc);
- else
- val = Expression::make_var_reference(this->var_, loc);
- Expression* closed = Expression::make_var_reference(this->closedvar_,
- loc);
- Statement* s = Statement::make_tuple_receive_assignment(val, closed, ref,
- true, loc);
+ this->lower_send(b, selref, chanref, index_expr);
+ else
+ this->lower_recv(gogo, function, b, selref, chanref, index_expr);
- // We have to put S in STATEMENTS_, because that is where the
- // variables are declared.
+ // Now all references should be handled through the statements, not
+ // through here.
+ this->is_lowered_ = true;
+ this->val_ = NULL;
+ this->var_ = NULL;
+}
- go_assert(this->statements_ != NULL);
+// Lower a default clause in a select statement.
- // Skip the variable declaration statements themselves.
- size_t skip = 1;
- if (this->var_ != NULL)
- skip = 2;
+void
+Select_clauses::Select_clause::lower_default(Block* b, Expression* selref,
+ Expression* index_expr)
+{
+ Location loc = this->location_;
+ Expression* call = Runtime::make_call(Runtime::SELECTDEFAULT, loc, 2, selref,
+ index_expr);
+ b->add_statement(Statement::make_statement(call, true));
+}
- // Verify that we are only skipping variable declarations.
- size_t i = 0;
- for (Block::iterator p = this->statements_->begin();
- i < skip && p != this->statements_->end();
- ++p, ++i)
- go_assert((*p)->variable_declaration_statement() != NULL);
+// Lower a send clause in a select statement.
- this->statements_->insert_statement_before(skip, s);
+void
+Select_clauses::Select_clause::lower_send(Block* b, Expression* selref,
+ Expression* chanref,
+ Expression* index_expr)
+{
+ Location loc = this->location_;
- // We have to lower STATEMENTS_ again, to lower the tuple
- // receive assignment we just added.
- gogo->lower_block(function, this->statements_);
- }
+ Channel_type* ct = this->channel_->type()->channel_type();
+ if (ct == NULL)
+ return;
+
+ Type* valtype = ct->element_type();
+
+ // Note that copying the value to a temporary here means that we
+ // evaluate the send values in the required order.
+ Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
+ loc);
+ b->add_statement(val);
+
+ Expression* valref = Expression::make_temporary_reference(val, loc);
+ Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
+
+ Expression* call = Runtime::make_call(Runtime::SELECTSEND, loc, 4, selref,
+ chanref, valaddr, index_expr);
+ b->add_statement(Statement::make_statement(call, true));
+}
+
+// Lower a receive clause in a select statement.
+
+void
+Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
+ Block* b, Expression* selref,
+ Expression* chanref,
+ Expression* index_expr)
+{
+ Location loc = this->location_;
+
+ Channel_type* ct = this->channel_->type()->channel_type();
+ if (ct == NULL)
+ return;
+
+ Type* valtype = ct->element_type();
+ Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
+ b->add_statement(val);
+
+ Expression* valref = Expression::make_temporary_reference(val, loc);
+ Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
+
+ Temporary_statement* closed_temp = NULL;
+
+ Expression* call;
+ if (this->closed_ == NULL && this->closedvar_ == NULL)
+ call = Runtime::make_call(Runtime::SELECTRECV, loc, 4, selref, chanref,
+ valaddr, index_expr);
else
{
- Receive_expression* recv = Expression::make_receive(ref, loc);
- recv->set_for_select();
- if (this->val_ != NULL)
- {
- go_assert(this->var_ == NULL);
- init->add_statement(Statement::make_assignment(this->val_, recv,
- loc));
- }
- else if (this->var_ != NULL)
- {
- this->var_->var_value()->set_init(recv);
- this->var_->var_value()->clear_type_from_chan_element();
- }
- else
- {
- init->add_statement(Statement::make_statement(recv, true));
- }
+ closed_temp = Statement::make_temporary(Type::lookup_bool_type(), NULL,
+ loc);
+ b->add_statement(closed_temp);
+ Expression* cref = Expression::make_temporary_reference(closed_temp,
+ loc);
+ Expression* caddr = Expression::make_unary(OPERATOR_AND, cref, loc);
+ call = Runtime::make_call(Runtime::SELECTRECV2, loc, 5, selref, chanref,
+ valaddr, caddr, index_expr);
}
- // Lower any statements we just created.
- gogo->lower_block(function, init);
+ b->add_statement(Statement::make_statement(call, true));
- if (this->statements_ != NULL)
- init->add_statement(Statement::make_block_statement(this->statements_,
- loc));
+ // If the block of statements is executed, arrange for the received
+ // value to move from VAL to the place where the statements expect
+ // it.
- this->statements_ = init;
+ Block* init = NULL;
- // Now all references should be handled through the statements, not
- // through here.
- this->is_lowered_ = true;
- this->val_ = NULL;
- this->var_ = NULL;
+ if (this->var_ != NULL)
+ {
+ go_assert(this->val_ == NULL);
+ valref = Expression::make_temporary_reference(val, loc);
+ this->var_->var_value()->set_init(valref);
+ this->var_->var_value()->clear_type_from_chan_element();
+ }
+ else if (this->val_ != NULL && !this->val_->is_sink_expression())
+ {
+ init = new Block(b, loc);
+ valref = Expression::make_temporary_reference(val, loc);
+ init->add_statement(Statement::make_assignment(this->val_, valref, loc));
+ }
+
+ if (this->closedvar_ != NULL)
+ {
+ go_assert(this->closed_ == NULL);
+ Expression* cref = Expression::make_temporary_reference(closed_temp,
+ loc);
+ this->closedvar_->var_value()->set_init(cref);
+ }
+ else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
+ {
+ if (init == NULL)
+ init = new Block(b, loc);
+ Expression* cref = Expression::make_temporary_reference(closed_temp,
+ loc);
+ init->add_statement(Statement::make_assignment(this->closed_, cref,
+ loc));
+ }
+
+ if (init != NULL)
+ {
+ gogo->lower_block(function, init);
+
+ if (this->statements_ != NULL)
+ init->add_statement(Statement::make_block_statement(this->statements_,
+ loc));
+ this->statements_ = init;
+ }
}
// Determine types.
@@ -4630,6 +4671,27 @@ Select_clauses::Select_clause::determine_types()
this->statements_->determine_types();
}
+// Check types.
+
+void
+Select_clauses::Select_clause::check_types()
+{
+ if (this->is_default_)
+ return;
+
+ Channel_type* ct = this->channel_->type()->channel_type();
+ if (ct == NULL)
+ {
+ error_at(this->channel_->location(), "expected channel");
+ return;
+ }
+
+ if (this->is_send_ && !ct->may_send())
+ error_at(this->location(), "invalid send on receive-only channel");
+ else if (!this->is_send_ && !ct->may_receive())
+ error_at(this->location(), "invalid receive on send-only channel");
+}
+
// Whether this clause may fall through to the statement which follows
// the overall select statement.
@@ -4717,12 +4779,13 @@ Select_clauses::traverse(Traverse* traverse)
// receive statements to the clauses.
void
-Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b)
+Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
+ Temporary_statement* sel)
{
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
++p)
- p->lower(gogo, function, b);
+ p->lower(gogo, function, b, sel);
}
// Determine types.
@@ -4736,6 +4799,17 @@ Select_clauses::determine_types()
p->determine_types();
}
+// Check types.
+
+void
+Select_clauses::check_types()
+{
+ for (Clauses::iterator p = this->clauses_.begin();
+ p != this->clauses_.end();
+ ++p)
+ p->check_types();
+}
+
// Return whether these select clauses fall through to the statement
// following the overall select statement.
@@ -4750,179 +4824,55 @@ Select_clauses::may_fall_through() const
return false;
}
-// Convert to the backend representation. We build a call to
-// size_t __go_select(size_t count, _Bool has_default,
-// channel* channels, _Bool* is_send)
-//
-// There are COUNT entries in the CHANNELS and IS_SEND arrays. The
-// value in the IS_SEND array is true for send, false for receive.
-// __go_select returns an integer from 0 to COUNT, inclusive. A
-// return of 0 means that the default case should be run; this only
-// happens if HAS_DEFAULT is non-zero. Otherwise the number indicates
-// the case to run.
-
-// FIXME: This doesn't handle channels which send interface types
-// where the receiver has a static type which matches that interface.
+// Convert to the backend representation. We have already accumulated
+// all the select information. Now we call selectgo, which will
+// return the index of the clause to execute.
Bstatement*
Select_clauses::get_backend(Translate_context* context,
+ Temporary_statement* sel,
Unnamed_label *break_label,
Location location)
{
size_t count = this->clauses_.size();
+ std::vector<std::vector<Bexpression*> > cases(count);
+ std::vector<Bstatement*> clauses(count);
- Expression_list* chan_init = new Expression_list();
- chan_init->reserve(count);
-
- Expression_list* is_send_init = new Expression_list();
- is_send_init->reserve(count);
-
- Select_clause *default_clause = NULL;
-
- Type* runtime_chanptr_type = Runtime::chanptr_type();
- Type* runtime_chan_type = runtime_chanptr_type->points_to();
-
+ int i = 0;
for (Clauses::iterator p = this->clauses_.begin();
p != this->clauses_.end();
- ++p)
+ ++p, ++i)
{
- if (p->is_default())
- {
- default_clause = &*p;
- --count;
- continue;
- }
-
- if (p->channel()->type()->channel_type() == NULL)
- {
- // We should have given an error in the send or receive
- // statement we created via lowering.
- go_assert(saw_errors());
- return context->backend()->error_statement();
- }
-
- Expression* c = p->channel();
- c = Expression::make_unsafe_cast(runtime_chan_type, c, p->location());
- chan_init->push_back(c);
+ int index = p->index();
+ mpz_t ival;
+ mpz_init_set_ui(ival, index);
+ Expression* index_expr = Expression::make_integer(&ival, NULL, location);
+ mpz_clear(ival);
+ cases[i].push_back(tree_to_expr(index_expr->get_tree(context)));
- is_send_init->push_back(Expression::make_boolean(p->is_send(),
- p->location()));
- }
+ Bstatement* s = p->get_statements_backend(context);
+ Location gloc = (p->statements() == NULL
+ ? p->location()
+ : p->statements()->end_location());
+ Bstatement* g = break_label->get_goto(context, gloc);
- if (chan_init->empty())
- {
- go_assert(count == 0);
- Bstatement* s;
- Bstatement* ldef = break_label->get_definition(context);
- if (default_clause != NULL)
- {
- // There is a default clause and no cases. Just execute the
- // default clause.
- s = default_clause->get_statements_backend(context);
- }
- else
- {
- // There isn't even a default clause. In this case select
- // pauses forever. Call the runtime function with nils.
- mpz_t zval;
- mpz_init_set_ui(zval, 0);
- Expression* zero = Expression::make_integer(&zval, NULL, location);
- mpz_clear(zval);
- Expression* default_arg = Expression::make_boolean(false, location);
- Expression* nil1 = Expression::make_nil(location);
- Expression* nil2 = nil1->copy();
- Expression* call = Runtime::make_call(Runtime::SELECT, location, 4,
- zero, default_arg, nil1, nil2);
- context->gogo()->lower_expression(context->function(), NULL, &call);
- Bexpression* bcall = tree_to_expr(call->get_tree(context));
- s = context->backend()->expression_statement(bcall);
- }
if (s == NULL)
- return ldef;
- return context->backend()->compound_statement(s, ldef);
+ clauses[i] = g;
+ else
+ clauses[i] = context->backend()->compound_statement(s, g);
}
- go_assert(count > 0);
-
- std::vector<Bstatement*> statements;
- mpz_t ival;
- mpz_init_set_ui(ival, count);
- Expression* ecount = Expression::make_integer(&ival, NULL, location);
- mpz_clear(ival);
-
- Type* chan_array_type = Type::make_array_type(runtime_chan_type, ecount);
- Expression* chans = Expression::make_composite_literal(chan_array_type, 0,
- false, chan_init,
- location);
- context->gogo()->lower_expression(context->function(), NULL, &chans);
- Temporary_statement* chan_temp = Statement::make_temporary(chan_array_type,
- chans,
- location);
- statements.push_back(chan_temp->get_backend(context));
-
- Type* is_send_array_type = Type::make_array_type(Type::lookup_bool_type(),
- ecount->copy());
- Expression* is_sends = Expression::make_composite_literal(is_send_array_type,
- 0, false,
- is_send_init,
- location);
- context->gogo()->lower_expression(context->function(), NULL, &is_sends);
- Temporary_statement* is_send_temp =
- Statement::make_temporary(is_send_array_type, is_sends, location);
- statements.push_back(is_send_temp->get_backend(context));
-
- mpz_init_set_ui(ival, 0);
- Expression* zero = Expression::make_integer(&ival, NULL, location);
- mpz_clear(ival);
-
- Expression* ref = Expression::make_temporary_reference(chan_temp, location);
- Expression* chan_arg = Expression::make_array_index(ref, zero, NULL,
- location);
- chan_arg = Expression::make_unary(OPERATOR_AND, chan_arg, location);
- chan_arg = Expression::make_unsafe_cast(runtime_chanptr_type, chan_arg,
- location);
-
- ref = Expression::make_temporary_reference(is_send_temp, location);
- Expression* is_send_arg = Expression::make_array_index(ref, zero->copy(),
- NULL, location);
- is_send_arg = Expression::make_unary(OPERATOR_AND, is_send_arg, location);
-
- Expression* default_arg = Expression::make_boolean(default_clause != NULL,
- location);
- Expression* call = Runtime::make_call(Runtime::SELECT, location, 4,
- ecount->copy(), default_arg,
- chan_arg, is_send_arg);
+ Expression* selref = Expression::make_temporary_reference(sel, location);
+ Expression* call = Runtime::make_call(Runtime::SELECTGO, location, 1,
+ selref);
context->gogo()->lower_expression(context->function(), NULL, &call);
Bexpression* bcall = tree_to_expr(call->get_tree(context));
- std::vector<std::vector<Bexpression*> > cases;
- std::vector<Bstatement*> clauses;
+ if (count == 0)
+ return context->backend()->expression_statement(bcall);
- cases.resize(count + (default_clause != NULL ? 1 : 0));
- clauses.resize(count + (default_clause != NULL ? 1 : 0));
-
- int index = 0;
-
- if (default_clause != NULL)
- {
- this->add_clause_backend(context, location, index, 0, default_clause,
- break_label, &cases, &clauses);
- ++index;
- }
-
- int i = 1;
- for (Clauses::iterator p = this->clauses_.begin();
- p != this->clauses_.end();
- ++p)
- {
- if (!p->is_default())
- {
- this->add_clause_backend(context, location, index, i, &*p,
- break_label, &cases, &clauses);
- ++i;
- ++index;
- }
- }
+ std::vector<Bstatement*> statements;
+ statements.reserve(2);
Bstatement* switch_stmt = context->backend()->switch_statement(bcall,
cases,
@@ -4935,39 +4885,6 @@ Select_clauses::get_backend(Translate_context* context,
return context->backend()->statement_list(statements);
}
-
-// Add CLAUSE to CASES/CLAUSES at INDEX.
-
-void
-Select_clauses::add_clause_backend(
- Translate_context* context,
- Location location,
- int index,
- int case_value,
- Select_clause* clause,
- Unnamed_label* bottom_label,
- std::vector<std::vector<Bexpression*> > *cases,
- std::vector<Bstatement*>* clauses)
-{
- mpz_t ival;
- mpz_init_set_ui(ival, case_value);
- Expression* e = Expression::make_integer(&ival, NULL, location);
- mpz_clear(ival);
- (*cases)[index].push_back(tree_to_expr(e->get_tree(context)));
-
- Bstatement* s = clause->get_statements_backend(context);
-
- Location gloc = (clause->statements() == NULL
- ? clause->location()
- : clause->statements()->end_location());
- Bstatement* g = bottom_label->get_goto(context, gloc);
-
- if (s == NULL)
- (*clauses)[index] = g;
- else
- (*clauses)[index] = context->backend()->compound_statement(s, g);
-}
-
// Dump the AST representation for select clauses.
void
@@ -5003,11 +4920,28 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
{
if (this->is_lowered_)
return this;
- Block* b = new Block(enclosing, this->location());
- this->clauses_->lower(gogo, function, b);
+
+ Location loc = this->location();
+
+ Block* b = new Block(enclosing, loc);
+
+ go_assert(this->sel_ == NULL);
+
+ mpz_t ival;
+ mpz_init_set_ui(ival, this->clauses_->size());
+ Expression* size_expr = Expression::make_integer(&ival, NULL, loc);
+ mpz_clear(ival);
+
+ Expression* call = Runtime::make_call(Runtime::NEWSELECT, loc, 1, size_expr);
+
+ this->sel_ = Statement::make_temporary(NULL, call, loc);
+ b->add_statement(this->sel_);
+
+ this->clauses_->lower(gogo, function, b, this->sel_);
this->is_lowered_ = true;
b->add_statement(this);
- return Statement::make_block_statement(b, this->location());
+
+ return Statement::make_block_statement(b, loc);
}
// Return the backend representation for a select statement.
@@ -5015,7 +4949,7 @@ Select_statement::do_lower(Gogo* gogo, Named_object* function,
Bstatement*
Select_statement::do_get_backend(Translate_context* context)
{
- return this->clauses_->get_backend(context, this->break_label(),
+ return this->clauses_->get_backend(context, this->sel_, this->break_label(),
this->location());
}
@@ -5790,7 +5724,7 @@ For_range_statement::lower_range_channel(Gogo*,
Expression::make_temporary_reference(ok_temp, loc);
oref->set_is_lvalue();
Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
- false, loc);
+ loc);
iter_init->add_statement(s);
Block* then_block = new Block(iter_init, loc);
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 16914f16c37..4548ba6f56c 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -165,12 +165,10 @@ class Statement
Expression* should_set, Location);
// Make an assignment from a nonblocking receive to a pair of
- // variables. FOR_SELECT is true is this is being created for a
- // case x, ok := <-c in a select statement.
+ // variables.
static Statement*
make_tuple_receive_assignment(Expression* val, Expression* closed,
- Expression* channel, bool for_select,
- Location);
+ Expression* channel, Location);
// Make an assignment from a type guard to a pair of variables.
static Statement*
@@ -634,14 +632,9 @@ class Send_statement : public Statement
Send_statement(Expression* channel, Expression* val,
Location location)
: Statement(STATEMENT_SEND, location),
- channel_(channel), val_(val), for_select_(false)
+ channel_(channel), val_(val)
{ }
- // Note that this is for a select statement.
- void
- set_for_select()
- { this->for_select_ = true; }
-
protected:
int
do_traverse(Traverse* traverse);
@@ -663,8 +656,6 @@ class Send_statement : public Statement
Expression* channel_;
// The value to send.
Expression* val_;
- // Whether this is for a select statement.
- bool for_select_;
};
// Select_clauses holds the clauses of a select statement. This is
@@ -693,23 +684,32 @@ class Select_clauses
Named_object* var, Named_object* closedvar, bool is_default,
Block* statements, Location location)
{
- this->clauses_.push_back(Select_clause(is_send, channel, val, closed, var,
- closedvar, is_default, statements,
- location));
+ int index = static_cast<int>(this->clauses_.size());
+ this->clauses_.push_back(Select_clause(index, is_send, channel, val,
+ closed, var, closedvar, is_default,
+ statements, location));
}
+ size_t
+ size() const
+ { return this->clauses_.size(); }
+
// Traverse the select clauses.
int
traverse(Traverse*);
// Lower statements.
void
- lower(Gogo*, Named_object*, Block*);
+ lower(Gogo*, Named_object*, Block*, Temporary_statement*);
// Determine types.
void
determine_types();
+ // Check types.
+ void
+ check_types();
+
// Whether the select clauses may fall through to the statement
// which follows the overall select statement.
bool
@@ -717,7 +717,8 @@ class Select_clauses
// Convert to the backend representation.
Bstatement*
- get_backend(Translate_context*, Unnamed_label* break_label, Location);
+ get_backend(Translate_context*, Temporary_statement* sel,
+ Unnamed_label* break_label, Location);
// Dump AST representation.
void
@@ -734,27 +735,37 @@ class Select_clauses
is_default_(false)
{ }
- Select_clause(bool is_send, Expression* channel, Expression* val,
- Expression* closed, Named_object* var,
+ Select_clause(int index, bool is_send, Expression* channel,
+ Expression* val, Expression* closed, Named_object* var,
Named_object* closedvar, bool is_default, Block* statements,
Location location)
- : 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)
+ : index_(index), 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)
{ go_assert(is_default ? channel == NULL : channel != NULL); }
+ // Return the index of this clause.
+ int
+ index() const
+ { return this->index_; }
+
// Traverse the select clause.
int
traverse(Traverse*);
// Lower statements.
void
- lower(Gogo*, Named_object*, Block*);
+ lower(Gogo*, Named_object*, Block*, Temporary_statement*);
// Determine types.
void
determine_types();
+ // Check types.
+ void
+ check_types();
+
// Return true if this is the default clause.
bool
is_default() const
@@ -798,6 +809,18 @@ class Select_clauses
dump_clause(Ast_dump_context*) const;
private:
+ void
+ lower_default(Block*, Expression*, Expression*);
+
+ void
+ lower_send(Block*, Expression*, Expression*, Expression*);
+
+ void
+ lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*,
+ Expression*);
+
+ // The index of this case in the generated switch statement.
+ int index_;
// The channel.
Expression* channel_;
// The value to send or the lvalue to receive into.
@@ -822,12 +845,6 @@ class Select_clauses
bool is_lowered_;
};
- void
- add_clause_backend(Translate_context*, Location, int index,
- int case_value, Select_clause*, Unnamed_label*,
- std::vector<std::vector<Bexpression*> >* cases,
- std::vector<Bstatement*>* clauses);
-
typedef std::vector<Select_clause> Clauses;
Clauses clauses_;
@@ -840,7 +857,7 @@ class Select_statement : public Statement
public:
Select_statement(Location location)
: Statement(STATEMENT_SELECT, location),
- clauses_(NULL), break_label_(NULL), is_lowered_(false)
+ clauses_(NULL), sel_(NULL), break_label_(NULL), is_lowered_(false)
{ }
// Add the clauses.
@@ -867,6 +884,10 @@ class Select_statement : public Statement
do_determine_types()
{ this->clauses_->determine_types(); }
+ void
+ do_check_types(Gogo*)
+ { this->clauses_->check_types(); }
+
bool
do_may_fall_through() const
{ return this->clauses_->may_fall_through(); }
@@ -880,6 +901,8 @@ class Select_statement : public Statement
private:
// The select clauses.
Select_clauses* clauses_;
+ // A temporary which holds the select structure we build up at runtime.
+ Temporary_statement* sel_;
// The break label.
Unnamed_label* break_label_;
// Whether this statement has been lowered.
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 3dadf8d12d7..e3c6b3ce824 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -246,6 +246,14 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
struct function *caller_cfun = DECL_STRUCT_FUNCTION (e->caller->decl);
struct function *callee_cfun
= callee ? DECL_STRUCT_FUNCTION (callee->decl) : NULL;
+ bool call_stmt_cannot_inline_p;
+
+ /* If E has a call statement in it, use the inline attribute from
+ the statement, otherwise use the inline attribute in E. Edges
+ will not have statements when working in WPA mode. */
+ call_stmt_cannot_inline_p = (e->call_stmt)
+ ? gimple_call_cannot_inline_p (e->call_stmt)
+ : e->call_stmt_cannot_inline_p;
if (!caller_cfun && e->caller->clone_of)
caller_cfun = DECL_STRUCT_FUNCTION (e->caller->clone_of->decl);
@@ -270,7 +278,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
e->inline_failed = CIF_OVERWRITABLE;
return false;
}
- else if (e->call_stmt_cannot_inline_p)
+ else if (call_stmt_cannot_inline_p)
{
e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
inlinable = false;
@@ -343,14 +351,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
}
}
- /* Be sure that the cannot_inline_p flag is up to date. */
- gcc_checking_assert (!e->call_stmt
- || (gimple_call_cannot_inline_p (e->call_stmt)
- == e->call_stmt_cannot_inline_p)
- /* In -flto-partition=none mode we really keep things out of
- sync because call_stmt_cannot_inline_p is set at cgraph
- merging when function bodies are not there yet. */
- || (in_lto_p && !gimple_call_cannot_inline_p (e->call_stmt)));
if (!inlinable && report)
report_inline_failed_reason (e);
return inlinable;
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 6deff4141a3..378b933baf0 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -1,5 +1,5 @@
/* Loop unrolling and peeling.
- Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -2262,10 +2262,15 @@ apply_opt_in_copies (struct opt_info *opt_info,
for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = next)
{
next = NEXT_INSN (insn);
- if (!INSN_P (insn))
+ if (!INSN_P (insn)
+ || (DEBUG_INSN_P (insn)
+ && TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL))
continue;
- while (!INSN_P (orig_insn))
+ while (!INSN_P (orig_insn)
+ || (DEBUG_INSN_P (orig_insn)
+ && (TREE_CODE (INSN_VAR_LOCATION_DECL (orig_insn))
+ == LABEL_DECL)))
orig_insn = NEXT_INSN (orig_insn);
ivts_templ.insn = orig_insn;
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index af849540ea8..6f13e04220e 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * lto-lang.c (lto_attribute_table): Handle *tm regparm.
+ (ignore_attribute): New.
+
2011-11-21 Aldy Hernandez <aldyh@redhat.com>
* lto-lang.c (lto_attribute_table): Handle transaction_pure.
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 2536f26ebf0..0d230eeddca 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -47,6 +47,8 @@ static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
+
static tree handle_format_attribute (tree *, tree, tree, int, bool *);
static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
@@ -78,6 +80,10 @@ const struct attribute_spec lto_attribute_table[] =
handle_type_generic_attribute, false },
{ "transaction_pure", 0, 0, false, true, true,
handle_transaction_pure_attribute, false },
+ /* For internal use only. The leading '*' both prevents its usage in
+ source code and signals that it may be overridden by machine tables. */
+ { "*tm regparm", 0, 0, false, true, true,
+ ignore_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -419,6 +425,18 @@ handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+/* Ignore the given attribute. Used when this attribute may be usefully
+ overridden by the target, but is not used generically. */
+
+static tree
+ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
/* Handle a "format" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8e29dab0ade..cd9e27e77f8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,43 @@
+2011-12-01 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/initlist61.C: New.
+
+2011-12-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51326
+ * g++.dg/inherit/crash3.C: New.
+
+2011-12-01 Nathan Sidwell <nathan@acm.org>
+
+ PR gcov-profile/51113
+ * lib/gcov.exp (verify-lines): Add support for xfailing.
+ (run-gcov): Likewise.
+ * gcc.misc-tests/gcov-13.c: Xfail weak function.
+ * gcc.misc-tests/gcov-16.c: Remove.
+ * gcc.misc-tests/gcov-17.c: Remove.
+ * g++.dg/gcov-8.C: Remove.
+ * g++.dg/gcov-9.C: Remove.
+ * g++.dg/gcovpart-12b.C: New.
+ * g++.dg/gcov-12.C: New.
+
+2011-12-01 Andrew Pinski <apinski@cavium.com>
+
+ PR lto/51198
+ * g++.dg/torture/pr51198.C: New testcase.
+
+2011-12-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/51246
+ * gcc.c-torture/compile/pr51246.c: New test.
+
+ PR rtl-optimization/51014
+ * g++.dg/opt/pr51014.C: New test.
+
+2011-12-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/51367
+ * g++.dg/template/error47.C: New.
+
2011-11-30 Jason Merrill <jason@redhat.com>
PR c++/51009
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist61.C b/gcc/testsuite/g++.dg/cpp0x/initlist61.C
new file mode 100644
index 00000000000..28eccc2637d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist61.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+
+struct N { N(int); };
+struct A { N i,j; };
+
+int main()
+{
+ A* ap = new A{1,2};
+}
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-12.C b/gcc/testsuite/g++.dg/gcov/gcov-12.C
new file mode 100644
index 00000000000..c4708e40726
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-12.C
@@ -0,0 +1,21 @@
+/* PR 51113 */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fpic" } */
+/* { dg-do run { target native } } */
+/* { dg-additional-sources "gcovpart-12b.C" } */
+
+struct Foo {
+ Foo ()
+ {} /* count(1) */
+ virtual void Func () /* count(#####) */
+ {} /* count(#####) */
+};
+
+int main ()
+{
+ Foo b;
+
+ return 0; /* count (1) */
+}
+
+/* { dg-final { run-gcov gcov-12.C } } */
+/* { dg-final { run-gcov gcovpart-12b.C { xfail *-*-* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-8.C b/gcc/testsuite/g++.dg/gcov/gcov-8.C
deleted file mode 100644
index 272cefc373b..00000000000
--- a/gcc/testsuite/g++.dg/gcov/gcov-8.C
+++ /dev/null
@@ -1,14 +0,0 @@
-/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
-/* { dg-require-visibility "" } */
-
-struct __attribute__((visibility ("hidden"))) X
-{
- void Fink ();
-};
-
-void X::Fink ()
-{
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov___ZN1X4FinkEv" { target { ! *-*-darwin* } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov___ZN1X4FinkEv" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-9.C b/gcc/testsuite/g++.dg/gcov/gcov-9.C
deleted file mode 100644
index b9c64d22e56..00000000000
--- a/gcc/testsuite/g++.dg/gcov/gcov-9.C
+++ /dev/null
@@ -1,17 +0,0 @@
-/* { dg-options "-fprofile-arcs -fvisibility-inlines-hidden" } */
-/* { dg-require-visibility "" } */
-
-inline void Boo ()
-{
-}
-
-extern "C" void (*Foo ()) ()
-{
- return Boo;
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov___Z3Boov" { target { ! *-*-darwin* } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov___Z3Boov" { target *-*-darwin* } } } */
-/* { dg-final { scan-assembler "__gcov__Foo:" } } */
-/* { dg-final { scan-assembler-not "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
-/* { dg-final { scan-assembler-not "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C b/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C
new file mode 100644
index 00000000000..6a1f981f0df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C
@@ -0,0 +1,5 @@
+struct Foo {
+ Foo () {}
+ virtual void Func () /* count(-) { xfail *-*-* } */
+ {} /* count(-) { xfail *-*-* } */
+};
diff --git a/gcc/testsuite/g++.dg/inherit/crash3.C b/gcc/testsuite/g++.dg/inherit/crash3.C
new file mode 100644
index 00000000000..e6094b04a64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/crash3.C
@@ -0,0 +1,11 @@
+// PR c++/51326
+
+struct A
+{
+ virtual int& foo(); // { dg-error "overriding" }
+};
+
+struct B : A
+{
+ B& foo(); // { dg-error "conflicting return type" }
+};
diff --git a/gcc/testsuite/g++.dg/opt/pr51014.C b/gcc/testsuite/g++.dg/opt/pr51014.C
new file mode 100644
index 00000000000..1e5bb9f0f14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr51014.C
@@ -0,0 +1,16 @@
+// PR rtl-optimization/51014
+// { dg-do compile }
+// { dg-options "-O2 -funroll-loops -fcompare-debug" }
+
+struct S
+{
+ ~S() { delete s; }
+ int *s;
+};
+
+void
+f (S *x, S *y)
+{
+ for (; x != y; ++x)
+ x->~S();
+}
diff --git a/gcc/testsuite/g++.dg/template/error47.C b/gcc/testsuite/g++.dg/template/error47.C
new file mode 100644
index 00000000000..7e360fe69a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error47.C
@@ -0,0 +1,9 @@
+// PR c++/51367
+
+template<typename T> void foo(T, T); // { dg-message "template" }
+
+void bar(void* p)
+{
+ foo(0, p); // { dg-error "no matching" }
+}
+// { dg-message "candidate|parameter 'T' ('int' and 'void*')" { target *-*-* } 7 }
diff --git a/gcc/testsuite/g++.dg/torture/pr51198.C b/gcc/testsuite/g++.dg/torture/pr51198.C
new file mode 100644
index 00000000000..65009ff5458
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr51198.C
@@ -0,0 +1,29 @@
+/* { dg-options "-std=gnu++0x" } */
+
+struct A
+{
+ int i = 0 ? 0 : throw 1;
+};
+
+
+struct B
+{
+ int f();
+ int i = f();
+};
+
+struct C
+{
+ C(int);
+};
+
+struct D
+{
+ C a = 0;
+};
+
+A a;
+B b;
+D d;
+
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr51246.c b/gcc/testsuite/gcc.c-torture/compile/pr51246.c
new file mode 100644
index 00000000000..c206d8689f1
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr51246.c
@@ -0,0 +1,14 @@
+/* PR tree-optimization/51246 */
+
+int a, *b;
+
+void
+test (void)
+{
+ while (1)
+ {
+ int c;
+ a = c;
+ b = &c;
+ }
+}
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-13.c b/gcc/testsuite/gcc.misc-tests/gcov-13.c
index 14be8f9e103..fa9680b2544 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-13.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-13.c
@@ -7,7 +7,7 @@
int __attribute__ ((weak)) weak ()
{
- return 1; /* count(-) */
+ return 1; /* count(-) { xfail *-*-* } */
}
int main ()
@@ -15,5 +15,5 @@ int main ()
return weak (); /* count(1) */
}
-/* { dg-final { run-gcov { -a gcov-13.c } } } */
+/* { dg-final { run-gcov { -a gcov-13.c } { xfail *-*-* } } } */
/* { dg-final { run-gcov { -a gcovpart-13b.c } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-16.c b/gcc/testsuite/gcc.misc-tests/gcov-16.c
deleted file mode 100644
index 478f44a367d..00000000000
--- a/gcc/testsuite/gcc.misc-tests/gcov-16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Test visibility is copied */
-
-/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
-/* { dg-require-visibility "" } */
-/* { dg-require-weak "" } */
-
-void Foo ()
-{
-}
-
- /* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
- /* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-17.c b/gcc/testsuite/gcc.misc-tests/gcov-17.c
deleted file mode 100644
index f8ff794215c..00000000000
--- a/gcc/testsuite/gcc.misc-tests/gcov-17.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Test visibility is copied */
-
-/* { dg-options "-fprofile-arcs" } */
-/* { dg-require-visibility "" } */
-/* { dg-require-weak "" } */
-
-void __attribute__ ((visibility ("hidden"), weak)) Foo ()
-{
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin* } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp
index 1c7484785db..081b3ceb14c 100644
--- a/gcc/testsuite/lib/gcov.exp
+++ b/gcc/testsuite/lib/gcov.exp
@@ -39,19 +39,28 @@ proc clean-gcov { testcase } {
#
proc verify-lines { testcase file } {
#send_user "verify-lines\n"
+ global subdir
set failed 0
set fd [open $file r]
while { [gets $fd line] >= 0 } {
# We want to match both "-" and "#####" as count as well as numbers,
# since we want to detect lines that shouldn't be marked as covered.
- if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#]+)\\)" \
- "$line" all is n shouldbe] {
+ if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#]+)\\)(.*)" \
+ "$line" all is n shouldbe rest] {
+ if [regexp "^ *{(.*)}" $rest all xfailed] {
+ switch [dg-process-target $xfailed] {
+ "N" { continue }
+ "F" { setup_xfail "*-*-*" }
+ }
+ }
if { $is == "" } {
- fail "$n:no data available for this line"
+ fail "$subdir/$testcase:$n:no data available for this line"
incr failed
} elseif { $is != $shouldbe } {
- fail "$n:is $is:should be $shouldbe"
+ fail "$subdir/$testcase:$n:is $is:should be $shouldbe"
incr failed
+ } else {
+ pass "$subdir/$testcase:$n line count"
}
}
}
@@ -230,32 +239,36 @@ proc run-gcov { args } {
global GCOV
global srcdir subdir
- set gcov_args [lindex $args end]
-
+ set gcov_args ""
set gcov_verify_calls 0
set gcov_verify_branches 0
- set gcov_execute_xfail ""
- set gcov_verify_xfail ""
+ set xfailed 0
foreach a $args {
if { $a == "calls" } {
set gcov_verify_calls 1
} elseif { $a == "branches" } {
set gcov_verify_branches 1
+ } elseif { $gcov_args == "" } {
+ set gcov_args $a
+ } else {
+ switch [dg-process-target $a] {
+ "N" { return }
+ "F" { set xfailed 1 }
+ }
}
}
# Extract the test name from the arguments.
set testcase [lindex $gcov_args end]
- if { $gcov_execute_xfail != "" } {
- eval setup_xfail [split $gcov_execute_xfail]
- }
-
verbose "Running $GCOV $testcase" 2
set testcase [remote_download host $testcase]
set result [remote_exec host $GCOV $gcov_args]
if { [lindex $result 0] != 0 } {
+ if { $xfailed } {
+ setup_xfail "*-*-*"
+ }
fail "$subdir/$testcase gcov failed: [lindex $result 1]"
clean-gcov $testcase
return
@@ -264,16 +277,15 @@ proc run-gcov { args } {
# Get the gcov output file after making sure it exists.
set files [glob -nocomplain $testcase.gcov]
if { $files == "" } {
+ if { $xfailed } {
+ setup_xfail "*-*-*"
+ }
fail "$subdir/$testcase gcov failed: $testcase.gcov does not exist"
clean-gcov $testcase
return
}
remote_upload host $testcase.gcov $testcase.gcov
- if { $gcov_verify_xfail != "" } {
- eval setup_xfail [split $gcov_verify_xfail]
- }
-
# Check that line execution counts are as expected.
set lfailed [verify-lines $testcase $testcase.gcov]
@@ -293,6 +305,9 @@ proc run-gcov { args } {
# Report whether the gcov test passed or failed. If there were
# multiple failures then the message is a summary.
set tfailed [expr $lfailed + $bfailed + $cfailed]
+ if { $xfailed } {
+ setup_xfail "*-*-*"
+ }
if { $tfailed > 0 } {
fail "$subdir/$testcase gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages"
} else {
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index c55c89e9b71..751bdebfa8a 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -1306,8 +1306,20 @@ replace_ref_with (gimple stmt, tree new_tree, bool set, bool in_lhs)
val = gimple_assign_lhs (stmt);
if (TREE_CODE (val) != SSA_NAME)
{
- gcc_assert (gimple_assign_copy_p (stmt));
val = gimple_assign_rhs1 (stmt);
+ gcc_assert (gimple_assign_single_p (stmt));
+ if (TREE_CLOBBER_P (val))
+ {
+ val = gimple_default_def (cfun, SSA_NAME_VAR (new_tree));
+ if (val == NULL_TREE)
+ {
+ val = make_ssa_name (SSA_NAME_VAR (new_tree),
+ gimple_build_nop ());
+ set_default_def (SSA_NAME_VAR (new_tree), val);
+ }
+ }
+ else
+ gcc_assert (gimple_assign_copy_p (stmt));
}
}
else
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index d6fbe622df0..a710de620df 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1215,6 +1215,26 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb)
ei_next (&ei);
}
+ /* If this is a store into a variable that is being optimized away,
+ add a debug bind stmt if possible. */
+ if (MAY_HAVE_DEBUG_STMTS
+ && gimple_assign_single_p (stmt)
+ && is_gimple_val (gimple_assign_rhs1 (stmt)))
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ if ((TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
+ && !DECL_IGNORED_P (lhs)
+ && is_gimple_reg_type (TREE_TYPE (lhs))
+ && !is_global_var (lhs)
+ && !DECL_HAS_VALUE_EXPR_P (lhs))
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+ gimple note
+ = gimple_build_debug_bind (lhs, unshare_expr (rhs), stmt);
+ gsi_insert_after (i, note, GSI_SAME_STMT);
+ }
+ }
+
unlink_stmt_vdef (stmt);
gsi_remove (i, true);
release_defs (stmt);
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index b8a056ebdac..103e4f7155a 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -1,5 +1,5 @@
/* Liveness for SSA trees.
- Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@redhat.com>
@@ -814,7 +814,15 @@ remove_unused_locals (void)
bitmap_set_bit (global_unused_vars, DECL_UID (var));
}
else
- continue;
+ {
+ /* For unreferenced local vars drop TREE_ADDRESSABLE
+ bit in case it is referenced from debug stmts. */
+ if (DECL_CONTEXT (var) == current_function_decl
+ && TREE_ADDRESSABLE (var)
+ && is_gimple_reg_type (TREE_TYPE (var)))
+ TREE_ADDRESSABLE (var) = 0;
+ continue;
+ }
}
else if (TREE_CODE (var) == VAR_DECL
&& DECL_HARD_REGISTER (var)
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 22414475f6f..306bac28c18 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -2074,6 +2074,8 @@ vect_recog_bool_pattern (VEC (gimple, heap) **stmts, tree *type_in,
stmt_vec_info pattern_stmt_info;
vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
gcc_assert (vectype != NULL_TREE);
+ if (!VECTOR_MODE_P (TYPE_MODE (vectype)))
+ return NULL;
if (!check_bool_pattern (var, loop_vinfo))
return NULL;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 5cbc25fcb1e..494cdd3e030 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -7284,7 +7284,9 @@ simplify_conversion_using_ranges (gimple stmt)
tree innerop, middleop, finaltype;
gimple def_stmt;
value_range_t *innervr;
- double_int innermin, innermax, middlemin, middlemax;
+ bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p;
+ unsigned inner_prec, middle_prec, final_prec;
+ double_int innermin, innermed, innermax, middlemin, middlemed, middlemax;
finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
if (!INTEGRAL_TYPE_P (finaltype))
@@ -7309,33 +7311,49 @@ simplify_conversion_using_ranges (gimple stmt)
the middle conversion is removed. */
innermin = tree_to_double_int (innervr->min);
innermax = tree_to_double_int (innervr->max);
- middlemin = double_int_ext (innermin, TYPE_PRECISION (TREE_TYPE (middleop)),
- TYPE_UNSIGNED (TREE_TYPE (middleop)));
- middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)),
- TYPE_UNSIGNED (TREE_TYPE (middleop)));
- /* If the middle values are not equal to the original values fail.
- But only if the inner cast truncates (thus we ignore differences
- in extension to handle the case going from a range to an anti-range
- and back). */
- if ((TYPE_PRECISION (TREE_TYPE (innerop))
- > TYPE_PRECISION (TREE_TYPE (middleop)))
- && (!double_int_equal_p (innermin, middlemin)
- || !double_int_equal_p (innermax, middlemax)))
+
+ inner_prec = TYPE_PRECISION (TREE_TYPE (innerop));
+ middle_prec = TYPE_PRECISION (TREE_TYPE (middleop));
+ final_prec = TYPE_PRECISION (finaltype);
+
+ /* If the first conversion is not injective, the second must not
+ be widening. */
+ if (double_int_cmp (double_int_sub (innermax, innermin),
+ double_int_mask (middle_prec), true) > 0
+ && middle_prec < final_prec)
return false;
+ /* We also want a medium value so that we can track the effect that
+ narrowing conversions with sign change have. */
+ inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop));
+ if (inner_unsigned_p)
+ innermed = double_int_rshift (double_int_mask (inner_prec),
+ 1, inner_prec, false);
+ else
+ innermed = double_int_zero;
+ if (double_int_cmp (innermin, innermed, inner_unsigned_p) >= 0
+ || double_int_cmp (innermed, innermax, inner_unsigned_p) >= 0)
+ innermed = innermin;
+
+ middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop));
+ middlemin = double_int_ext (innermin, middle_prec, middle_unsigned_p);
+ middlemed = double_int_ext (innermed, middle_prec, middle_unsigned_p);
+ middlemax = double_int_ext (innermax, middle_prec, middle_unsigned_p);
+
/* Require that the final conversion applied to both the original
and the intermediate range produces the same result. */
+ final_unsigned_p = TYPE_UNSIGNED (finaltype);
if (!double_int_equal_p (double_int_ext (middlemin,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)),
+ final_prec, final_unsigned_p),
double_int_ext (innermin,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)))
+ final_prec, final_unsigned_p))
+ || !double_int_equal_p (double_int_ext (middlemed,
+ final_prec, final_unsigned_p),
+ double_int_ext (innermed,
+ final_prec, final_unsigned_p))
|| !double_int_equal_p (double_int_ext (middlemax,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype)),
+ final_prec, final_unsigned_p),
double_int_ext (innermax,
- TYPE_PRECISION (finaltype),
- TYPE_UNSIGNED (finaltype))))
+ final_prec, final_unsigned_p)))
return false;
gimple_assign_set_rhs1 (stmt, innerop);
diff --git a/gcc/tree.c b/gcc/tree.c
index 72603b59945..4cadc7ef8c4 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4651,7 +4651,8 @@ free_lang_data_in_decl (tree decl)
|| (decl_function_context (decl) && !TREE_STATIC (decl)))
DECL_INITIAL (decl) = NULL_TREE;
}
- else if (TREE_CODE (decl) == TYPE_DECL)
+ else if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == FIELD_DECL)
DECL_INITIAL (decl) = NULL_TREE;
else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
&& DECL_INITIAL (decl)
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 5ab10a61f3d..19ce7152cf1 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -409,10 +409,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-can-convert-interface.c \
runtime/go-cgo.c \
- runtime/go-chan-cap.c \
- runtime/go-chan-len.c \
runtime/go-check-interface.c \
- runtime/go-close.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
@@ -432,27 +429,16 @@ runtime_files = \
runtime/go-map-len.c \
runtime/go-map-range.c \
runtime/go-nanotime.c \
- runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c \
- runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c \
runtime/go-recover.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-select.c \
- runtime/go-send-big.c \
- runtime/go-send-nb-big.c \
- runtime/go-send-nb-small.c \
- runtime/go-send-small.c \
runtime/go-setenv.c \
runtime/go-signal.c \
runtime/go-strcmp.c \
@@ -473,6 +459,7 @@ runtime_files = \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
+ runtime/chan.c \
runtime/cpuprof.c \
$(runtime_lock_files) \
runtime/mcache.c \
@@ -488,7 +475,6 @@ runtime_files = \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
- chan.c \
iface.c \
malloc.c \
map.c \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index f7c293a66cc..1a76f0b5a20 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -183,8 +183,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-assert-interface.c \
runtime/go-byte-array-to-string.c runtime/go-breakpoint.c \
runtime/go-caller.c runtime/go-can-convert-interface.c \
- runtime/go-cgo.c runtime/go-chan-cap.c runtime/go-chan-len.c \
- runtime/go-check-interface.c runtime/go-close.c \
+ runtime/go-cgo.c runtime/go-check-interface.c \
runtime/go-construct-map.c runtime/go-convert-interface.c \
runtime/go-copy.c runtime/go-defer.c \
runtime/go-deferred-recover.c runtime/go-eface-compare.c \
@@ -195,17 +194,11 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-interface-val-compare.c runtime/go-make-slice.c \
runtime/go-map-delete.c runtime/go-map-index.c \
runtime/go-map-len.c runtime/go-map-range.c \
- runtime/go-nanotime.c runtime/go-new-channel.c \
- runtime/go-new-map.c runtime/go-new.c runtime/go-panic.c \
- runtime/go-print.c runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c runtime/go-recover.c \
+ runtime/go-nanotime.c runtime/go-new-map.c runtime/go-new.c \
+ runtime/go-panic.c runtime/go-print.c runtime/go-recover.c \
runtime/go-reflect.c runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c runtime/go-reflect-map.c \
- runtime/go-rune.c runtime/go-runtime-error.c \
- runtime/go-select.c runtime/go-send-big.c \
- runtime/go-send-nb-big.c runtime/go-send-nb-small.c \
- runtime/go-send-small.c runtime/go-setenv.c \
+ runtime/go-reflect-map.c runtime/go-rune.c \
+ runtime/go-runtime-error.c runtime/go-setenv.c \
runtime/go-signal.c runtime/go-strcmp.c \
runtime/go-string-to-byte-array.c \
runtime/go-string-to-int-array.c runtime/go-strplus.c \
@@ -215,15 +208,15 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-type-string.c runtime/go-typedesc-equal.c \
runtime/go-typestring.c runtime/go-unreflect.c \
runtime/go-unsafe-new.c runtime/go-unsafe-newarray.c \
- runtime/go-unsafe-pointer.c runtime/go-unwind.c \
+ runtime/go-unsafe-pointer.c runtime/go-unwind.c runtime/chan.c \
runtime/cpuprof.c runtime/lock_sema.c runtime/thread-sema.c \
runtime/lock_futex.c runtime/thread-linux.c runtime/mcache.c \
runtime/mcentral.c runtime/mem_posix_memalign.c runtime/mem.c \
runtime/mfinal.c runtime/mfixalloc.c runtime/mgc0.c \
runtime/mheap.c runtime/msize.c runtime/proc.c \
runtime/runtime.c runtime/thread.c runtime/yield.c \
- runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
- map.c mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c
+ runtime/rtems-task-variable-add.c iface.c malloc.c map.c \
+ mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c
@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
@@ -231,8 +224,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
- go-can-convert-interface.lo go-cgo.lo go-chan-cap.lo \
- go-chan-len.lo go-check-interface.lo go-close.lo \
+ go-can-convert-interface.lo go-cgo.lo go-check-interface.lo \
go-construct-map.lo go-convert-interface.lo go-copy.lo \
go-defer.lo go-deferred-recover.lo go-eface-compare.lo \
go-eface-val-compare.lo go-getgoroot.lo \
@@ -240,23 +232,20 @@ am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
go-interface-compare.lo go-interface-eface-compare.lo \
go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \
go-map-index.lo go-map-len.lo go-map-range.lo go-nanotime.lo \
- go-new-channel.lo go-new-map.lo go-new.lo go-panic.lo \
- go-print.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
- go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
- go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
- go-runtime-error.lo go-select.lo go-send-big.lo \
- go-send-nb-big.lo go-send-nb-small.lo go-send-small.lo \
- go-setenv.lo go-signal.lo go-strcmp.lo \
+ go-new-map.lo go-new.lo go-panic.lo go-print.lo go-recover.lo \
+ go-reflect.lo go-reflect-call.lo go-reflect-map.lo go-rune.lo \
+ go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \
go-string-to-byte-array.lo go-string-to-int-array.lo \
go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
go-type-error.lo go-type-identity.lo go-type-interface.lo \
go-type-string.lo go-typedesc-equal.lo go-typestring.lo \
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
- go-unsafe-pointer.lo go-unwind.lo cpuprof.lo $(am__objects_1) \
- mcache.lo mcentral.lo $(am__objects_2) mfinal.lo mfixalloc.lo \
- mgc0.lo mheap.lo msize.lo proc.lo runtime.lo thread.lo \
- yield.lo $(am__objects_3) chan.lo iface.lo malloc.lo map.lo \
- mprof.lo reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo
+ go-unsafe-pointer.lo go-unwind.lo chan.lo cpuprof.lo \
+ $(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \
+ mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo proc.lo \
+ runtime.lo thread.lo yield.lo $(am__objects_3) iface.lo \
+ malloc.lo map.lo mprof.lo reflect.lo runtime1.lo sema.lo \
+ sigqueue.lo string.lo
am_libgo_la_OBJECTS = $(am__objects_4)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -836,10 +825,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-can-convert-interface.c \
runtime/go-cgo.c \
- runtime/go-chan-cap.c \
- runtime/go-chan-len.c \
runtime/go-check-interface.c \
- runtime/go-close.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
@@ -859,27 +845,16 @@ runtime_files = \
runtime/go-map-len.c \
runtime/go-map-range.c \
runtime/go-nanotime.c \
- runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c \
- runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c \
runtime/go-recover.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-select.c \
- runtime/go-send-big.c \
- runtime/go-send-nb-big.c \
- runtime/go-send-nb-small.c \
- runtime/go-send-small.c \
runtime/go-setenv.c \
runtime/go-signal.c \
runtime/go-strcmp.c \
@@ -900,6 +875,7 @@ runtime_files = \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
+ runtime/chan.c \
runtime/cpuprof.c \
$(runtime_lock_files) \
runtime/mcache.c \
@@ -915,7 +891,6 @@ runtime_files = \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
- chan.c \
iface.c \
malloc.c \
map.c \
@@ -2461,10 +2436,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-chan-cap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-chan-len.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-close.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-convert-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-copy.Plo@am__quote@
@@ -2485,27 +2457,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-len.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-range.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nanotime.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-channel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-small.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-small.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-recover.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-chan.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-select.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-small.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-small.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@
@@ -2645,20 +2606,6 @@ go-cgo.lo: runtime/go-cgo.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
-go-chan-cap.lo: runtime/go-chan-cap.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-chan-cap.lo -MD -MP -MF $(DEPDIR)/go-chan-cap.Tpo -c -o go-chan-cap.lo `test -f 'runtime/go-chan-cap.c' || echo '$(srcdir)/'`runtime/go-chan-cap.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-chan-cap.Tpo $(DEPDIR)/go-chan-cap.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-chan-cap.c' object='go-chan-cap.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-chan-cap.lo `test -f 'runtime/go-chan-cap.c' || echo '$(srcdir)/'`runtime/go-chan-cap.c
-
-go-chan-len.lo: runtime/go-chan-len.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-chan-len.lo -MD -MP -MF $(DEPDIR)/go-chan-len.Tpo -c -o go-chan-len.lo `test -f 'runtime/go-chan-len.c' || echo '$(srcdir)/'`runtime/go-chan-len.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-chan-len.Tpo $(DEPDIR)/go-chan-len.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-chan-len.c' object='go-chan-len.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-chan-len.lo `test -f 'runtime/go-chan-len.c' || echo '$(srcdir)/'`runtime/go-chan-len.c
-
go-check-interface.lo: runtime/go-check-interface.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-check-interface.lo -MD -MP -MF $(DEPDIR)/go-check-interface.Tpo -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-check-interface.Tpo $(DEPDIR)/go-check-interface.Plo
@@ -2666,13 +2613,6 @@ go-check-interface.lo: runtime/go-check-interface.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
-go-close.lo: runtime/go-close.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-close.lo -MD -MP -MF $(DEPDIR)/go-close.Tpo -c -o go-close.lo `test -f 'runtime/go-close.c' || echo '$(srcdir)/'`runtime/go-close.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-close.Tpo $(DEPDIR)/go-close.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-close.c' object='go-close.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-close.lo `test -f 'runtime/go-close.c' || echo '$(srcdir)/'`runtime/go-close.c
-
go-construct-map.lo: runtime/go-construct-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-construct-map.lo -MD -MP -MF $(DEPDIR)/go-construct-map.Tpo -c -o go-construct-map.lo `test -f 'runtime/go-construct-map.c' || echo '$(srcdir)/'`runtime/go-construct-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-construct-map.Tpo $(DEPDIR)/go-construct-map.Plo
@@ -2806,13 +2746,6 @@ go-nanotime.lo: runtime/go-nanotime.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-nanotime.lo `test -f 'runtime/go-nanotime.c' || echo '$(srcdir)/'`runtime/go-nanotime.c
-go-new-channel.lo: runtime/go-new-channel.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new-channel.lo -MD -MP -MF $(DEPDIR)/go-new-channel.Tpo -c -o go-new-channel.lo `test -f 'runtime/go-new-channel.c' || echo '$(srcdir)/'`runtime/go-new-channel.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-new-channel.Tpo $(DEPDIR)/go-new-channel.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-new-channel.c' object='go-new-channel.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-new-channel.lo `test -f 'runtime/go-new-channel.c' || echo '$(srcdir)/'`runtime/go-new-channel.c
-
go-new-map.lo: runtime/go-new-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new-map.lo -MD -MP -MF $(DEPDIR)/go-new-map.Tpo -c -o go-new-map.lo `test -f 'runtime/go-new-map.c' || echo '$(srcdir)/'`runtime/go-new-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-new-map.Tpo $(DEPDIR)/go-new-map.Plo
@@ -2841,34 +2774,6 @@ go-print.lo: runtime/go-print.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
-go-rec-big.lo: runtime/go-rec-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-big.lo -MD -MP -MF $(DEPDIR)/go-rec-big.Tpo -c -o go-rec-big.lo `test -f 'runtime/go-rec-big.c' || echo '$(srcdir)/'`runtime/go-rec-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-big.Tpo $(DEPDIR)/go-rec-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-big.c' object='go-rec-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-big.lo `test -f 'runtime/go-rec-big.c' || echo '$(srcdir)/'`runtime/go-rec-big.c
-
-go-rec-nb-big.lo: runtime/go-rec-nb-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-nb-big.lo -MD -MP -MF $(DEPDIR)/go-rec-nb-big.Tpo -c -o go-rec-nb-big.lo `test -f 'runtime/go-rec-nb-big.c' || echo '$(srcdir)/'`runtime/go-rec-nb-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-nb-big.Tpo $(DEPDIR)/go-rec-nb-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-nb-big.c' object='go-rec-nb-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-nb-big.lo `test -f 'runtime/go-rec-nb-big.c' || echo '$(srcdir)/'`runtime/go-rec-nb-big.c
-
-go-rec-nb-small.lo: runtime/go-rec-nb-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-nb-small.lo -MD -MP -MF $(DEPDIR)/go-rec-nb-small.Tpo -c -o go-rec-nb-small.lo `test -f 'runtime/go-rec-nb-small.c' || echo '$(srcdir)/'`runtime/go-rec-nb-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-nb-small.Tpo $(DEPDIR)/go-rec-nb-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-nb-small.c' object='go-rec-nb-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-nb-small.lo `test -f 'runtime/go-rec-nb-small.c' || echo '$(srcdir)/'`runtime/go-rec-nb-small.c
-
-go-rec-small.lo: runtime/go-rec-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-small.lo -MD -MP -MF $(DEPDIR)/go-rec-small.Tpo -c -o go-rec-small.lo `test -f 'runtime/go-rec-small.c' || echo '$(srcdir)/'`runtime/go-rec-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-small.Tpo $(DEPDIR)/go-rec-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-small.c' object='go-rec-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-small.lo `test -f 'runtime/go-rec-small.c' || echo '$(srcdir)/'`runtime/go-rec-small.c
-
go-recover.lo: runtime/go-recover.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-recover.lo -MD -MP -MF $(DEPDIR)/go-recover.Tpo -c -o go-recover.lo `test -f 'runtime/go-recover.c' || echo '$(srcdir)/'`runtime/go-recover.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-recover.Tpo $(DEPDIR)/go-recover.Plo
@@ -2890,13 +2795,6 @@ go-reflect-call.lo: runtime/go-reflect-call.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c
-go-reflect-chan.lo: runtime/go-reflect-chan.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-chan.lo -MD -MP -MF $(DEPDIR)/go-reflect-chan.Tpo -c -o go-reflect-chan.lo `test -f 'runtime/go-reflect-chan.c' || echo '$(srcdir)/'`runtime/go-reflect-chan.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect-chan.Tpo $(DEPDIR)/go-reflect-chan.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-reflect-chan.c' object='go-reflect-chan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-chan.lo `test -f 'runtime/go-reflect-chan.c' || echo '$(srcdir)/'`runtime/go-reflect-chan.c
-
go-reflect-map.lo: runtime/go-reflect-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-map.lo -MD -MP -MF $(DEPDIR)/go-reflect-map.Tpo -c -o go-reflect-map.lo `test -f 'runtime/go-reflect-map.c' || echo '$(srcdir)/'`runtime/go-reflect-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect-map.Tpo $(DEPDIR)/go-reflect-map.Plo
@@ -2918,41 +2816,6 @@ go-runtime-error.lo: runtime/go-runtime-error.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c
-go-select.lo: runtime/go-select.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-select.lo -MD -MP -MF $(DEPDIR)/go-select.Tpo -c -o go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-select.Tpo $(DEPDIR)/go-select.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-select.c' object='go-select.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
-
-go-send-big.lo: runtime/go-send-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-big.lo -MD -MP -MF $(DEPDIR)/go-send-big.Tpo -c -o go-send-big.lo `test -f 'runtime/go-send-big.c' || echo '$(srcdir)/'`runtime/go-send-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-big.Tpo $(DEPDIR)/go-send-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-big.c' object='go-send-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-big.lo `test -f 'runtime/go-send-big.c' || echo '$(srcdir)/'`runtime/go-send-big.c
-
-go-send-nb-big.lo: runtime/go-send-nb-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-nb-big.lo -MD -MP -MF $(DEPDIR)/go-send-nb-big.Tpo -c -o go-send-nb-big.lo `test -f 'runtime/go-send-nb-big.c' || echo '$(srcdir)/'`runtime/go-send-nb-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-nb-big.Tpo $(DEPDIR)/go-send-nb-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-nb-big.c' object='go-send-nb-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-nb-big.lo `test -f 'runtime/go-send-nb-big.c' || echo '$(srcdir)/'`runtime/go-send-nb-big.c
-
-go-send-nb-small.lo: runtime/go-send-nb-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-nb-small.lo -MD -MP -MF $(DEPDIR)/go-send-nb-small.Tpo -c -o go-send-nb-small.lo `test -f 'runtime/go-send-nb-small.c' || echo '$(srcdir)/'`runtime/go-send-nb-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-nb-small.Tpo $(DEPDIR)/go-send-nb-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-nb-small.c' object='go-send-nb-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-nb-small.lo `test -f 'runtime/go-send-nb-small.c' || echo '$(srcdir)/'`runtime/go-send-nb-small.c
-
-go-send-small.lo: runtime/go-send-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-small.lo -MD -MP -MF $(DEPDIR)/go-send-small.Tpo -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-small.Tpo $(DEPDIR)/go-send-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-small.c' object='go-send-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
-
go-setenv.lo: runtime/go-setenv.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-setenv.lo -MD -MP -MF $(DEPDIR)/go-setenv.Tpo -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-setenv.Tpo $(DEPDIR)/go-setenv.Plo
@@ -3093,6 +2956,13 @@ go-unwind.lo: runtime/go-unwind.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c
+chan.lo: runtime/chan.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT chan.lo -MD -MP -MF $(DEPDIR)/chan.Tpo -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/chan.Tpo $(DEPDIR)/chan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/chan.c' object='chan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c
+
cpuprof.lo: runtime/cpuprof.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpuprof.lo -MD -MP -MF $(DEPDIR)/cpuprof.Tpo -c -o cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cpuprof.Tpo $(DEPDIR)/cpuprof.Plo
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
new file mode 100644
index 00000000000..a246992c60b
--- /dev/null
+++ b/libgo/runtime/chan.c
@@ -0,0 +1,1248 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "go-type.h"
+
+#define NOSELGEN 1
+
+static int32 debug = 0;
+
+typedef struct WaitQ WaitQ;
+typedef struct SudoG SudoG;
+typedef struct Select Select;
+typedef struct Scase Scase;
+
+typedef struct __go_type_descriptor Type;
+typedef struct __go_channel_type ChanType;
+
+struct SudoG
+{
+ G* g; // g and selgen constitute
+ uint32 selgen; // a weak pointer to g
+ SudoG* link;
+ byte* elem; // data element
+};
+
+struct WaitQ
+{
+ SudoG* first;
+ SudoG* last;
+};
+
+struct Hchan
+{
+ uint32 qcount; // total data in the q
+ uint32 dataqsiz; // size of the circular q
+ uint16 elemsize;
+ bool closed;
+ uint8 elemalign;
+ uint32 sendx; // send index
+ uint32 recvx; // receive index
+ WaitQ recvq; // list of recv waiters
+ WaitQ sendq; // list of send waiters
+ Lock;
+};
+
+// Buffer follows Hchan immediately in memory.
+// chanbuf(c, i) is pointer to the i'th slot in the buffer.
+#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
+
+enum
+{
+ // Scase.kind
+ CaseRecv,
+ CaseSend,
+ CaseDefault,
+};
+
+struct Scase
+{
+ SudoG sg; // must be first member (cast to Scase)
+ Hchan* chan; // chan
+ uint16 kind;
+ uint16 index; // index to return
+ bool* receivedp; // pointer to received bool (recv2)
+};
+
+struct Select
+{
+ uint16 tcase; // total count of scase[]
+ uint16 ncase; // currently filled scase[]
+ uint16* pollorder; // case poll order
+ Hchan** lockorder; // channel lock order
+ Scase scase[1]; // one per case (in order of appearance)
+};
+
+static void dequeueg(WaitQ*);
+static SudoG* dequeue(WaitQ*);
+static void enqueue(WaitQ*, SudoG*);
+
+Hchan*
+runtime_makechan_c(ChanType *t, int64 hint)
+{
+ Hchan *c;
+ int32 n;
+ const Type *elem;
+
+ elem = t->__element_type;
+
+ if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > ((uintptr)-1) / elem->__size))
+ runtime_panicstring("makechan: size out of range");
+
+ n = sizeof(*c);
+
+ // allocate memory in one call
+ c = (Hchan*)runtime_mal(n + hint*elem->__size);
+ c->elemsize = elem->__size;
+ c->elemalign = elem->__align;
+ c->dataqsiz = hint;
+
+ if(debug)
+ runtime_printf("makechan: chan=%p; elemsize=%lld; elemalign=%d; dataqsiz=%d\n",
+ c, (long long)elem->__size, elem->__align, c->dataqsiz);
+
+ return c;
+}
+
+// For reflect
+// func makechan(typ *ChanType, size uint32) (chan)
+uintptr reflect_makechan(ChanType *, uint32)
+ asm ("libgo_reflect.reflect.makechan");
+
+uintptr
+reflect_makechan(ChanType *t, uint32 size)
+{
+ void *ret;
+ Hchan *c;
+
+ c = runtime_makechan_c(t, size);
+ ret = runtime_mal(sizeof(void*));
+ __builtin_memcpy(ret, &c, sizeof(void*));
+ return (uintptr)ret;
+}
+
+// makechan(t *ChanType, hint int64) (hchan *chan any);
+Hchan*
+__go_new_channel(ChanType *t, uintptr hint)
+{
+ return runtime_makechan_c(t, hint);
+}
+
+/*
+ * generic single channel send/recv
+ * if the bool pointer is nil,
+ * then the full exchange will
+ * occur. if pres is not nil,
+ * then the protocol will not
+ * sleep but return if it could
+ * not complete.
+ *
+ * sleep can wake up with g->param == nil
+ * when a channel involved in the sleep has
+ * been closed. it is easiest to loop and re-run
+ * the operation; we'll see that it's now closed.
+ */
+void
+runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
+{
+ SudoG *sg;
+ SudoG mysg;
+ G* gp;
+ G* g;
+
+ g = runtime_g();
+
+ if(c == nil) {
+ USED(t);
+ if(pres != nil) {
+ *pres = false;
+ return;
+ }
+ g->status = Gwaiting;
+ g->waitreason = "chan send (nil chan)";
+ runtime_gosched();
+ return; // not reached
+ }
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug) {
+ runtime_printf("chansend: chan=%p\n", c);
+ }
+
+ runtime_lock(c);
+ if(c->closed)
+ goto closed;
+
+ if(c->dataqsiz > 0)
+ goto asynch;
+
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ runtime_unlock(c);
+
+ gp = sg->g;
+ gp->param = sg;
+ if(sg->elem != nil)
+ runtime_memmove(sg->elem, ep, c->elemsize);
+ runtime_ready(gp);
+
+ if(pres != nil)
+ *pres = true;
+ return;
+ }
+
+ if(pres != nil) {
+ runtime_unlock(c);
+ *pres = false;
+ return;
+ }
+
+ mysg.elem = ep;
+ mysg.g = g;
+ mysg.selgen = NOSELGEN;
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "chan send";
+ enqueue(&c->sendq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ if(g->param == nil) {
+ runtime_lock(c);
+ if(!c->closed)
+ runtime_throw("chansend: spurious wakeup");
+ goto closed;
+ }
+
+ return;
+
+asynch:
+ if(c->closed)
+ goto closed;
+
+ if(c->qcount >= c->dataqsiz) {
+ if(pres != nil) {
+ runtime_unlock(c);
+ *pres = false;
+ return;
+ }
+ mysg.g = g;
+ mysg.elem = nil;
+ mysg.selgen = NOSELGEN;
+ g->status = Gwaiting;
+ g->waitreason = "chan send";
+ enqueue(&c->sendq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ runtime_lock(c);
+ goto asynch;
+ }
+ runtime_memmove(chanbuf(c, c->sendx), ep, c->elemsize);
+ if(++c->sendx == c->dataqsiz)
+ c->sendx = 0;
+ c->qcount++;
+
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ gp = sg->g;
+ runtime_unlock(c);
+ runtime_ready(gp);
+ } else
+ runtime_unlock(c);
+ if(pres != nil)
+ *pres = true;
+ return;
+
+closed:
+ runtime_unlock(c);
+ runtime_panicstring("send on closed channel");
+}
+
+
+void
+runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received)
+{
+ SudoG *sg;
+ SudoG mysg;
+ G *gp;
+ G *g;
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug)
+ runtime_printf("chanrecv: chan=%p\n", c);
+
+ g = runtime_g();
+
+ if(c == nil) {
+ USED(t);
+ if(selected != nil) {
+ *selected = false;
+ return;
+ }
+ g->status = Gwaiting;
+ g->waitreason = "chan receive (nil chan)";
+ runtime_gosched();
+ return; // not reached
+ }
+
+ runtime_lock(c);
+ if(c->dataqsiz > 0)
+ goto asynch;
+
+ if(c->closed)
+ goto closed;
+
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ runtime_unlock(c);
+
+ if(ep != nil)
+ runtime_memmove(ep, sg->elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
+ return;
+ }
+
+ if(selected != nil) {
+ runtime_unlock(c);
+ *selected = false;
+ return;
+ }
+
+ mysg.elem = ep;
+ mysg.g = g;
+ mysg.selgen = NOSELGEN;
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "chan receive";
+ enqueue(&c->recvq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ if(g->param == nil) {
+ runtime_lock(c);
+ if(!c->closed)
+ runtime_throw("chanrecv: spurious wakeup");
+ goto closed;
+ }
+
+ if(received != nil)
+ *received = true;
+ return;
+
+asynch:
+ if(c->qcount <= 0) {
+ if(c->closed)
+ goto closed;
+
+ if(selected != nil) {
+ runtime_unlock(c);
+ *selected = false;
+ if(received != nil)
+ *received = false;
+ return;
+ }
+ mysg.g = g;
+ mysg.elem = nil;
+ mysg.selgen = NOSELGEN;
+ g->status = Gwaiting;
+ g->waitreason = "chan receive";
+ enqueue(&c->recvq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ runtime_lock(c);
+ goto asynch;
+ }
+ if(ep != nil)
+ runtime_memmove(ep, chanbuf(c, c->recvx), c->elemsize);
+ runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+ if(++c->recvx == c->dataqsiz)
+ c->recvx = 0;
+ c->qcount--;
+
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ gp = sg->g;
+ runtime_unlock(c);
+ runtime_ready(gp);
+ } else
+ runtime_unlock(c);
+
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
+ return;
+
+closed:
+ if(ep != nil)
+ runtime_memclr(ep, c->elemsize);
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = false;
+ runtime_unlock(c);
+}
+
+// The compiler generates a call to __go_send_small to send a value 8
+// bytes or smaller.
+void
+__go_send_small(ChanType *t, Hchan* c, uint64 val)
+{
+ byte b[sizeof(uint64)];
+
+ runtime_memclr(b, sizeof(uint64));
+ __builtin_memcpy(b, &val, t->__element_type->__size);
+ runtime_chansend(t, c, b, nil);
+}
+
+// The compiler generates a call to __go_send_big to send a value
+// larger than 8 bytes or smaller.
+void
+__go_send_big(ChanType *t, Hchan* c, byte* p)
+{
+ runtime_chansend(t, c, p, nil);
+}
+
+// The compiler generates a call to __go_receive_small to receive a
+// value 8 bytes or smaller.
+uint64
+__go_receive_small(ChanType *t, Hchan* c)
+{
+ union {
+ byte b[sizeof(uint64)];
+ uint64 v;
+ } u;
+
+ u.v = 0;
+ runtime_chanrecv(t, c, u.b, nil, nil);
+ return u.v;
+}
+
+// The compiler generates a call to __go_receive_big to receive a
+// value larger than 8 bytes.
+void
+__go_receive_big(ChanType *t, Hchan* c, byte* p)
+{
+ runtime_chanrecv(t, c, p, nil, nil);
+}
+
+_Bool runtime_chanrecv2(ChanType *t, Hchan* c, byte* p)
+ __asm__("runtime.chanrecv2");
+
+_Bool
+runtime_chanrecv2(ChanType *t, Hchan* c, byte* p)
+{
+ bool received;
+
+ runtime_chanrecv(t, c, p, nil, &received);
+ return received;
+}
+
+// func selectnbsend(c chan any, elem any) bool
+//
+// compiler implements
+//
+// select {
+// case c <- v:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbsend(c, v) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbsend(ChanType *t, Hchan *c, byte *p)
+{
+ bool res;
+
+ runtime_chansend(t, c, p, &res);
+ return res;
+}
+
+// func selectnbrecv(elem *any, c chan any) bool
+//
+// compiler implements
+//
+// select {
+// case v = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbrecv(&v, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c)
+{
+ bool selected;
+
+ runtime_chanrecv(t, c, v, &selected, nil);
+ return selected;
+}
+
+// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
+//
+// compiler implements
+//
+// select {
+// case v, ok = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if c != nil && selectnbrecv2(&v, &ok, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c)
+{
+ bool selected;
+ bool r;
+
+ r = false;
+ runtime_chanrecv(t, c, v, &selected, received == nil ? nil : &r);
+ if(received != nil)
+ *received = r;
+ return selected;
+}
+
+// For reflect:
+// func chansend(c chan, val iword, nb bool) (selected bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+
+_Bool reflect_chansend(ChanType *, Hchan *, uintptr, _Bool)
+ __asm__("libgo_reflect.reflect.chansend");
+
+_Bool
+reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb)
+{
+ bool selected;
+ bool *sp;
+ byte *vp;
+
+ if(nb) {
+ selected = false;
+ sp = (bool*)&selected;
+ } else {
+ selected = true;
+ sp = nil;
+ }
+ if(__go_is_pointer_type(t->__element_type))
+ vp = (byte*)&val;
+ else
+ vp = (byte*)val;
+ runtime_chansend(t, c, vp, sp);
+ return selected;
+}
+
+// For reflect:
+// func chanrecv(c chan, nb bool) (val iword, selected, received bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+
+struct chanrecv_ret
+{
+ uintptr val;
+ _Bool selected;
+ _Bool received;
+};
+
+struct chanrecv_ret reflect_chanrecv(ChanType *, Hchan *, _Bool)
+ __asm__("libgo_reflect.reflect.chanrecv");
+
+struct chanrecv_ret
+reflect_chanrecv(ChanType *t, Hchan *c, _Bool nb)
+{
+ struct chanrecv_ret ret;
+ byte *vp;
+ bool *sp;
+ bool selected;
+ bool received;
+
+ if(nb) {
+ selected = false;
+ sp = &selected;
+ } else {
+ ret.selected = true;
+ sp = nil;
+ }
+ received = false;
+ if(__go_is_pointer_type(t->__element_type)) {
+ vp = (byte*)&ret.val;
+ } else {
+ vp = runtime_mal(t->__element_type->__size);
+ ret.val = (uintptr)vp;
+ }
+ runtime_chanrecv(t, c, vp, sp, &received);
+ if(nb)
+ ret.selected = selected;
+ ret.received = received;
+ return ret;
+}
+
+static void newselect(int32, Select**);
+
+// newselect(size uint32) (sel *byte);
+
+void* runtime_newselect(int) __asm__("runtime.newselect");
+
+void*
+runtime_newselect(int size)
+{
+ Select *sel;
+
+ newselect(size, &sel);
+ return (void*)sel;
+}
+
+static void
+newselect(int32 size, Select **selp)
+{
+ int32 n;
+ Select *sel;
+
+ n = 0;
+ if(size > 1)
+ n = size-1;
+
+ sel = runtime_mal(sizeof(*sel) +
+ n*sizeof(sel->scase[0]) +
+ size*sizeof(sel->lockorder[0]) +
+ size*sizeof(sel->pollorder[0]));
+
+ sel->tcase = size;
+ sel->ncase = 0;
+ sel->pollorder = (void*)(sel->scase + size);
+ sel->lockorder = (void*)(sel->pollorder + size);
+ *selp = sel;
+
+ if(debug)
+ runtime_printf("newselect s=%p size=%d\n", sel, size);
+}
+
+// cut in half to give stack a chance to split
+static void selectsend(Select *sel, Hchan *c, int index, void *elem);
+
+// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
+
+void runtime_selectsend(Select *, Hchan *, void *, int)
+ __asm__("runtime.selectsend");
+
+void
+runtime_selectsend(Select *sel, Hchan *c, void *elem, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectsend(sel, c, index, elem);
+}
+
+static void
+selectsend(Select *sel, Hchan *c, int index, void *elem)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectsend: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+
+ cas->index = index;
+ cas->chan = c;
+ cas->kind = CaseSend;
+ cas->sg.elem = elem;
+
+ if(debug)
+ runtime_printf("selectsend s=%p index=%d chan=%p\n",
+ sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectrecv(Select *sel, Hchan *c, int index, void *elem, bool*);
+
+// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
+
+void runtime_selectrecv(Select *, Hchan *, void *, int)
+ __asm__("runtime.selectrecv");
+
+void
+runtime_selectrecv(Select *sel, Hchan *c, void *elem, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectrecv(sel, c, index, elem, nil);
+}
+
+// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
+
+void runtime_selectrecv2(Select *, Hchan *, void *, bool *, int)
+ __asm__("runtime.selectrecv2");
+
+void
+runtime_selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectrecv(sel, c, index, elem, received);
+}
+
+static void
+selectrecv(Select *sel, Hchan *c, int index, void *elem, bool *received)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectrecv: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+ cas->index = index;
+ cas->chan = c;
+
+ cas->kind = CaseRecv;
+ cas->sg.elem = elem;
+ cas->receivedp = received;
+
+ if(debug)
+ runtime_printf("selectrecv s=%p index=%d chan=%p\n",
+ sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectdefault(Select*, int);
+
+// selectdefault(sel *byte) (selected bool);
+
+void runtime_selectdefault(Select *, int) __asm__("runtime.selectdefault");
+
+void
+runtime_selectdefault(Select *sel, int index)
+{
+ selectdefault(sel, index);
+}
+
+static void
+selectdefault(Select *sel, int index)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectdefault: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+ cas->index = index;
+ cas->chan = nil;
+
+ cas->kind = CaseDefault;
+
+ if(debug)
+ runtime_printf("selectdefault s=%p index=%d\n",
+ sel, cas->index);
+}
+
+static void
+sellock(Select *sel)
+{
+ uint32 i;
+ Hchan *c, *c0;
+
+ c = nil;
+ for(i=0; i<sel->ncase; i++) {
+ c0 = sel->lockorder[i];
+ if(c0 && c0 != c) {
+ c = sel->lockorder[i];
+ runtime_lock(c);
+ }
+ }
+}
+
+static void
+selunlock(Select *sel)
+{
+ uint32 i;
+ Hchan *c, *c0;
+
+ c = nil;
+ for(i=sel->ncase; i-->0;) {
+ c0 = sel->lockorder[i];
+ if(c0 && c0 != c) {
+ c = c0;
+ runtime_unlock(c);
+ }
+ }
+}
+
+void
+runtime_block(void)
+{
+ G *g;
+
+ g = runtime_g();
+ g->status = Gwaiting; // forever
+ g->waitreason = "select (no cases)";
+ runtime_gosched();
+}
+
+static int selectgo(Select**);
+
+// selectgo(sel *byte);
+
+int runtime_selectgo(Select *) __asm__("runtime.selectgo");
+
+int
+runtime_selectgo(Select *sel)
+{
+ return selectgo(&sel);
+}
+
+static int
+selectgo(Select **selp)
+{
+ Select *sel;
+ uint32 o, i, j;
+ Scase *cas, *dfl;
+ Hchan *c;
+ SudoG *sg;
+ G *gp;
+ int index;
+ G *g;
+
+ sel = *selp;
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug)
+ runtime_printf("select: sel=%p\n", sel);
+
+ g = runtime_g();
+
+ // The compiler rewrites selects that statically have
+ // only 0 or 1 cases plus default into simpler constructs.
+ // The only way we can end up with such small sel->ncase
+ // values here is for a larger select in which most channels
+ // have been nilled out. The general code handles those
+ // cases correctly, and they are rare enough not to bother
+ // optimizing (and needing to test).
+
+ // generate permuted order
+ for(i=0; i<sel->ncase; i++)
+ sel->pollorder[i] = i;
+ for(i=1; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ j = runtime_fastrand1()%(i+1);
+ sel->pollorder[i] = sel->pollorder[j];
+ sel->pollorder[j] = o;
+ }
+
+ // sort the cases by Hchan address to get the locking order.
+ for(i=0; i<sel->ncase; i++) {
+ c = sel->scase[i].chan;
+ for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
+ sel->lockorder[j] = sel->lockorder[j-1];
+ sel->lockorder[j] = c;
+ }
+ sellock(sel);
+
+loop:
+ // pass 1 - look for something already waiting
+ dfl = nil;
+ for(i=0; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ cas = &sel->scase[o];
+ c = cas->chan;
+
+ switch(cas->kind) {
+ case CaseRecv:
+ if(c->dataqsiz > 0) {
+ if(c->qcount > 0)
+ goto asyncrecv;
+ } else {
+ sg = dequeue(&c->sendq);
+ if(sg != nil)
+ goto syncrecv;
+ }
+ if(c->closed)
+ goto rclose;
+ break;
+
+ case CaseSend:
+ if(c->closed)
+ goto sclose;
+ if(c->dataqsiz > 0) {
+ if(c->qcount < c->dataqsiz)
+ goto asyncsend;
+ } else {
+ sg = dequeue(&c->recvq);
+ if(sg != nil)
+ goto syncsend;
+ }
+ break;
+
+ case CaseDefault:
+ dfl = cas;
+ break;
+ }
+ }
+
+ if(dfl != nil) {
+ selunlock(sel);
+ cas = dfl;
+ goto retc;
+ }
+
+
+ // pass 2 - enqueue on all chans
+ for(i=0; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ cas = &sel->scase[o];
+ c = cas->chan;
+ sg = &cas->sg;
+ sg->g = g;
+ sg->selgen = g->selgen;
+
+ switch(cas->kind) {
+ case CaseRecv:
+ enqueue(&c->recvq, sg);
+ break;
+
+ case CaseSend:
+ enqueue(&c->sendq, sg);
+ break;
+ }
+ }
+
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "select";
+ selunlock(sel);
+ runtime_gosched();
+
+ sellock(sel);
+ sg = g->param;
+
+ // pass 3 - dequeue from unsuccessful chans
+ // otherwise they stack up on quiet channels
+ for(i=0; i<sel->ncase; i++) {
+ cas = &sel->scase[i];
+ if(cas != (Scase*)sg) {
+ c = cas->chan;
+ if(cas->kind == CaseSend)
+ dequeueg(&c->sendq);
+ else
+ dequeueg(&c->recvq);
+ }
+ }
+
+ if(sg == nil)
+ goto loop;
+
+ cas = (Scase*)sg;
+ c = cas->chan;
+
+ if(c->dataqsiz > 0)
+ runtime_throw("selectgo: shouldnt happen");
+
+ if(debug)
+ runtime_printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
+ sel, c, cas, cas->kind);
+
+ if(cas->kind == CaseRecv) {
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ }
+
+ selunlock(sel);
+ goto retc;
+
+asyncrecv:
+ // can receive from buffer
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ if(cas->sg.elem != nil)
+ runtime_memmove(cas->sg.elem, chanbuf(c, c->recvx), c->elemsize);
+ runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+ if(++c->recvx == c->dataqsiz)
+ c->recvx = 0;
+ c->qcount--;
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ gp = sg->g;
+ selunlock(sel);
+ runtime_ready(gp);
+ } else {
+ selunlock(sel);
+ }
+ goto retc;
+
+asyncsend:
+ // can send to buffer
+ runtime_memmove(chanbuf(c, c->sendx), cas->sg.elem, c->elemsize);
+ if(++c->sendx == c->dataqsiz)
+ c->sendx = 0;
+ c->qcount++;
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ gp = sg->g;
+ selunlock(sel);
+ runtime_ready(gp);
+ } else {
+ selunlock(sel);
+ }
+ goto retc;
+
+syncrecv:
+ // can receive from sleeping sender (sg)
+ selunlock(sel);
+ if(debug)
+ runtime_printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ if(cas->sg.elem != nil)
+ runtime_memmove(cas->sg.elem, sg->elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+ goto retc;
+
+rclose:
+ // read at end of closed channel
+ selunlock(sel);
+ if(cas->receivedp != nil)
+ *cas->receivedp = false;
+ if(cas->sg.elem != nil)
+ runtime_memclr(cas->sg.elem, c->elemsize);
+ goto retc;
+
+syncsend:
+ // can send to sleeping receiver (sg)
+ selunlock(sel);
+ if(debug)
+ runtime_printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
+ if(sg->elem != nil)
+ runtime_memmove(sg->elem, cas->sg.elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+
+retc:
+ // return index corresponding to chosen case
+ index = cas->index;
+ runtime_free(sel);
+ return index;
+
+sclose:
+ // send on closed channel
+ selunlock(sel);
+ runtime_panicstring("send on closed channel");
+ return 0; // not reached
+}
+
+// closechan(sel *byte);
+void
+runtime_closechan(Hchan *c)
+{
+ SudoG *sg;
+ G* gp;
+
+ if(c == nil)
+ runtime_panicstring("close of nil channel");
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ runtime_lock(c);
+ if(c->closed) {
+ runtime_unlock(c);
+ runtime_panicstring("close of closed channel");
+ }
+
+ c->closed = true;
+
+ // release all readers
+ for(;;) {
+ sg = dequeue(&c->recvq);
+ if(sg == nil)
+ break;
+ gp = sg->g;
+ gp->param = nil;
+ runtime_ready(gp);
+ }
+
+ // release all writers
+ for(;;) {
+ sg = dequeue(&c->sendq);
+ if(sg == nil)
+ break;
+ gp = sg->g;
+ gp->param = nil;
+ runtime_ready(gp);
+ }
+
+ runtime_unlock(c);
+}
+
+void
+__go_builtin_close(Hchan *c)
+{
+ runtime_closechan(c);
+}
+
+// For reflect
+// func chanclose(c chan)
+
+void reflect_chanclose(uintptr) __asm__("libgo_reflect.reflect.chanclose");
+
+void
+reflect_chanclose(uintptr c)
+{
+ runtime_closechan((Hchan*)c);
+}
+
+// For reflect
+// func chanlen(c chan) (len int32)
+
+int32 reflect_chanlen(uintptr) __asm__("libgo_reflect.reflect.chanlen");
+
+int32
+reflect_chanlen(uintptr ca)
+{
+ Hchan *c;
+ int32 len;
+
+ c = (Hchan*)ca;
+ if(c == nil)
+ len = 0;
+ else
+ len = c->qcount;
+ return len;
+}
+
+int
+__go_chan_len(Hchan *c)
+{
+ return reflect_chanlen((uintptr)c);
+}
+
+// For reflect
+// func chancap(c chan) (cap int32)
+
+int32 reflect_chancap(uintptr) __asm__("libgo_reflect.reflect.chancap");
+
+int32
+reflect_chancap(uintptr ca)
+{
+ Hchan *c;
+ int32 cap;
+
+ c = (Hchan*)ca;
+ if(c == nil)
+ cap = 0;
+ else
+ cap = c->dataqsiz;
+ return cap;
+}
+
+int
+__go_chan_cap(Hchan *c)
+{
+ return reflect_chancap((uintptr)c);
+}
+
+static SudoG*
+dequeue(WaitQ *q)
+{
+ SudoG *sgp;
+
+loop:
+ sgp = q->first;
+ if(sgp == nil)
+ return nil;
+ q->first = sgp->link;
+
+ // if sgp is stale, ignore it
+ if(sgp->selgen != NOSELGEN &&
+ (sgp->selgen != sgp->g->selgen ||
+ !runtime_cas(&sgp->g->selgen, sgp->selgen, sgp->selgen + 2))) {
+ //prints("INVALID PSEUDOG POINTER\n");
+ goto loop;
+ }
+
+ return sgp;
+}
+
+static void
+dequeueg(WaitQ *q)
+{
+ SudoG **l, *sgp, *prevsgp;
+ G *g;
+
+ g = runtime_g();
+ prevsgp = nil;
+ for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
+ if(sgp->g == g) {
+ *l = sgp->link;
+ if(q->last == sgp)
+ q->last = prevsgp;
+ break;
+ }
+ }
+}
+
+static void
+enqueue(WaitQ *q, SudoG *sgp)
+{
+ sgp->link = nil;
+ if(q->first == nil) {
+ q->first = sgp;
+ q->last = sgp;
+ return;
+ }
+ q->last->link = sgp;
+ q->last = sgp;
+}
diff --git a/libgo/runtime/chan.goc b/libgo/runtime/chan.goc
deleted file mode 100644
index c3cc3e39879..00000000000
--- a/libgo/runtime/chan.goc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-#include "config.h"
-#include "channel.h"
-
-#define nil NULL
-
-typedef _Bool bool;
-typedef unsigned char byte;
-typedef struct __go_channel chan;
-
-/* Do a channel receive with closed status. */
-
-func chanrecv2(c *chan, val *byte) (received bool) {
- uintptr_t element_size = c == nil ? 0 : c->element_type->__size;
- if (element_size > 8) {
- return __go_receive_big(c, val, 0);
- } else {
- union {
- char b[8];
- uint64_t v;
- } u;
-
- u.v = __go_receive_small_closed(c, 0, &received);
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, element_size);
-#else
- __builtin_memcpy(val, u.b + 8 - element_size, element_size);
-#endif
- return received;
- }
-}
-
-/* Do a channel receive with closed status for a select statement. */
-
-func chanrecv3(c *chan, val *byte) (received bool) {
- uintptr_t element_size = c->element_type->__size;
- if (element_size > 8) {
- return __go_receive_big(c, val, 1);
- } else {
- union {
- char b[8];
- uint64_t v;
- } u;
-
- u.v = __go_receive_small_closed(c, 1, &received);
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, element_size);
-#else
- __builtin_memcpy(val, u.b + 8 - element_size, element_size);
-#endif
- return received;
- }
-}
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
deleted file mode 100644
index 9176c68f692..00000000000
--- a/libgo/runtime/channel.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* channel.h -- the channel type for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-#include <pthread.h>
-
-#include "go-type.h"
-
-/* This structure is used when a select is waiting for a synchronous
- channel. */
-
-struct __go_channel_select
-{
- /* A pointer to the next select waiting for this channel. */
- struct __go_channel_select *next;
- /* A pointer to the channel which this select will use. This starts
- out as NULL and is set to the first channel which synchs up with
- this one. This variable to which this points may only be
- accessed when __go_select_data_mutex is held. */
- struct __go_channel **selected;
- /* A pointer to a variable which must be set to true if the
- goroutine which sets *SELECTED wants to read from the channel,
- false if it wants to write to it. */
- _Bool *is_read;
-};
-
-/* A channel is a pointer to this structure. */
-
-struct __go_channel
-{
- /* A mutex to control access to the channel. */
- pthread_mutex_t lock;
- /* A condition variable. This is signalled when data is added to
- the channel and when data is removed from the channel. */
- pthread_cond_t cond;
- /* The type of elements on this channel. */
- const struct __go_type_descriptor *element_type;
- /* True if a goroutine is waiting to send on a synchronous
- channel. */
- _Bool waiting_to_send;
- /* True if a goroutine is waiting to receive on a synchronous
- channel. */
- _Bool waiting_to_receive;
- /* True if this channel was selected for send in a select statement.
- This looks out all other sends. */
- _Bool selected_for_send;
- /* True if this channel was selected for receive in a select
- statement. This locks out all other receives. */
- _Bool selected_for_receive;
- /* True if this channel has been closed. */
- _Bool is_closed;
- /* The list of select statements waiting to send on a synchronous
- channel. */
- struct __go_channel_select *select_send_queue;
- /* The list of select statements waiting to receive on a synchronous
- channel. */
- struct __go_channel_select *select_receive_queue;
- /* If a select statement is waiting for this channel, it sets these
- pointers. When something happens on the channel, the channel
- locks the mutex, signals the condition, and unlocks the
- mutex. */
- pthread_mutex_t *select_mutex;
- pthread_cond_t *select_cond;
- /* The number of entries in the circular buffer. */
- unsigned int num_entries;
- /* Where to store the next value. */
- unsigned int next_store;
- /* Where to fetch the next value. If next_fetch == next_store, the
- buffer is empty. If next_store + 1 == next_fetch, the buffer is
- full. */
- unsigned int next_fetch;
- /* The circular buffer. */
- uint64_t data[];
-};
-
-/* Try to link up with the structure generated by the frontend. */
-typedef struct __go_channel __go_channel;
-
-/* The mutex used to control access to the value pointed to by the
- __go_channel_select selected field. No additional mutexes may be
- acquired while this mutex is held. */
-extern pthread_mutex_t __go_select_data_mutex;
-
-extern struct __go_channel *
-__go_new_channel (const struct __go_type_descriptor *, uintptr_t);
-
-extern _Bool __go_synch_with_select (struct __go_channel *, _Bool);
-
-extern void __go_broadcast_to_select (struct __go_channel *);
-
-extern void __go_send_acquire (struct __go_channel *, _Bool);
-
-extern _Bool __go_send_nonblocking_acquire (struct __go_channel *);
-
-extern void __go_send_release (struct __go_channel *);
-
-extern void __go_send_small (struct __go_channel *, uint64_t, _Bool);
-
-extern _Bool __go_send_nonblocking_small (struct __go_channel *, uint64_t);
-
-extern void __go_send_big (struct __go_channel *, const void *, _Bool);
-
-extern _Bool __go_send_nonblocking_big (struct __go_channel *, const void *);
-
-extern _Bool __go_receive_acquire (struct __go_channel *, _Bool);
-
-#define RECEIVE_NONBLOCKING_ACQUIRE_DATA 0
-#define RECEIVE_NONBLOCKING_ACQUIRE_NODATA 1
-#define RECEIVE_NONBLOCKING_ACQUIRE_CLOSED 2
-
-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
-{
- /* Value read from channel, or 0. */
- uint64_t __val;
- /* True if value was read from channel. */
- _Bool __success;
- /* True if channel is closed. */
- _Bool __closed;
-};
-
-extern struct __go_receive_nonblocking_small
-__go_receive_nonblocking_small (struct __go_channel *);
-
-extern _Bool __go_receive_big (struct __go_channel *, void *, _Bool);
-
-extern _Bool __go_receive_nonblocking_big (struct __go_channel *, void *,
- _Bool *);
-
-extern void __go_unlock_and_notify_selects (struct __go_channel *);
-
-extern _Bool __go_builtin_closed (struct __go_channel *);
-
-extern void __go_builtin_close (struct __go_channel *);
-
-extern int __go_chan_len (struct __go_channel *);
-
-extern int __go_chan_cap (struct __go_channel *);
-
-extern uintptr_t __go_select (uintptr_t, _Bool, struct __go_channel **,
- _Bool *);
diff --git a/libgo/runtime/go-chan-cap.c b/libgo/runtime/go-chan-cap.c
deleted file mode 100644
index 2c7958dd9fc..00000000000
--- a/libgo/runtime/go-chan-cap.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* go-chan-cap.c -- the cap function applied to a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-
-#include "go-assert.h"
-#include "channel.h"
-
-/* Return the cap function applied to a channel--the size of the
- buffer. This could be done inline but I'm doing it as a function
- for now to make it easy to change the channel structure. */
-
-int
-__go_chan_cap (struct __go_channel *channel)
-{
- int i;
- int ret;
-
- if (channel == NULL)
- return 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- if (channel->num_entries == 0)
- ret = 0;
- else
- {
- /* One slot is always unused. We added 1 when we created the
- channel. */
- ret = channel->num_entries - 1;
- }
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return ret;
-}
diff --git a/libgo/runtime/go-chan-len.c b/libgo/runtime/go-chan-len.c
deleted file mode 100644
index b3ced98aa05..00000000000
--- a/libgo/runtime/go-chan-len.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* go-chan-len.c -- the len function applied to a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-
-#include "go-assert.h"
-#include "channel.h"
-
-/* Return the len function applied to a channel--the number of
- elements in the buffer. This could be done inline but I'm doing it
- as a function for now to make it easy to change the channel
- structure. */
-
-int
-__go_chan_len (struct __go_channel *channel)
-{
- int i;
- int ret;
-
- if (channel == NULL)
- return 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- if (channel->num_entries == 0)
- ret = 0;
- else if (channel->next_fetch == channel->next_store)
- ret = 0;
- else
- ret = ((channel->next_store + channel->num_entries - channel->next_fetch)
- % channel->num_entries);
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return ret;
-}
diff --git a/libgo/runtime/go-close.c b/libgo/runtime/go-close.c
deleted file mode 100644
index 7e32286dae0..00000000000
--- a/libgo/runtime/go-close.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* go-close.c -- the builtin close function.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Close a channel. After a channel is closed, sends are no longer
- permitted. Receives always return zero. */
-
-void
-__go_builtin_close (struct __go_channel *channel)
-{
- int i;
-
- if (channel == NULL)
- runtime_panicstring ("close of nil channel");
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_send)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("close of closed channel");
- }
-
- channel->is_closed = 1;
-
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- __go_unlock_and_notify_selects (channel);
-}
diff --git a/libgo/runtime/go-new-channel.c b/libgo/runtime/go-new-channel.c
deleted file mode 100644
index fe13c5efab6..00000000000
--- a/libgo/runtime/go-new-channel.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* go-new-channel.c -- allocate a new channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "channel.h"
-
-struct __go_channel*
-__go_new_channel (const struct __go_type_descriptor *channel_type,
- uintptr_t entries)
-{
- const struct __go_channel_type *ctd;
- const struct __go_type_descriptor *element_type;
- uintptr_t element_size;
- int ientries;
- struct __go_channel* ret;
- size_t alloc_size;
- int i;
-
- __go_assert (channel_type->__code == GO_CHAN);
- ctd = (const struct __go_channel_type *) channel_type;
- element_type = ctd->__element_type;
-
- element_size = element_type->__size;
-
- ientries = (int) entries;
- if (ientries < 0
- || (uintptr_t) ientries != entries
- || (element_size > 0 && entries > (uintptr_t) -1 / element_size))
- runtime_panicstring ("chan size out of range");
-
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- /* We use a circular buffer which means that when next_fetch ==
- next_store we don't know whether the buffer is empty or full. So
- we allocate an extra space, and always leave a space open.
- FIXME. */
- if (entries != 0)
- ++entries;
-
- ret = (struct __go_channel*) __go_alloc (sizeof (struct __go_channel)
- + ((entries == 0 ? 1 : entries)
- * alloc_size
- * sizeof (uint64_t)));
- i = pthread_mutex_init (&ret->lock, NULL);
- __go_assert (i == 0);
- i = pthread_cond_init (&ret->cond, NULL);
- __go_assert (i == 0);
- ret->element_type = element_type;
- ret->waiting_to_send = 0;
- ret->waiting_to_receive = 0;
- ret->selected_for_send = 0;
- ret->selected_for_receive = 0;
- ret->is_closed = 0;
- ret->select_send_queue = NULL;
- ret->select_receive_queue = NULL;
- ret->select_mutex = NULL;
- ret->select_cond = NULL;
- ret->num_entries = entries;
- ret->next_store = 0;
- ret->next_fetch = 0;
- return ret;
-}
diff --git a/libgo/runtime/go-rec-big.c b/libgo/runtime/go-rec-big.c
deleted file mode 100644
index d45e90af476..00000000000
--- a/libgo/runtime/go-rec-big.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* go-rec-big.c -- receive something larger than 64 bits on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "go-panic.h"
-#include "channel.h"
-
-/* Returns true if a value was received, false if the channel is
- closed. */
-
-_Bool
-__go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- /* Block forever. */
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- if (!__go_receive_acquire (channel, for_select))
- {
- __builtin_memset (val, 0, element_size);
- return 0;
- }
-
- offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], element_size);
-
- __go_receive_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-rec-nb-big.c b/libgo/runtime/go-rec-nb-big.c
deleted file mode 100644
index 659ea1dc33d..00000000000
--- a/libgo/runtime/go-rec-nb-big.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* go-rec-nb-big.c -- nonblocking receive of something big on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "channel.h"
-
-/* Return true if a value was received, false if not. */
-
-_Bool
-__go_receive_nonblocking_big (struct __go_channel* channel, void *val,
- _Bool *closed)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- if (closed != NULL)
- *closed = 0;
- return 0;
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- int data = __go_receive_nonblocking_acquire (channel);
- if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
- {
- __builtin_memset (val, 0, element_size);
- if (closed != NULL)
- *closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- return 0;
- }
-
- offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], element_size);
-
- __go_receive_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
deleted file mode 100644
index c21878ce131..00000000000
--- a/libgo/runtime/go-rec-nb-small.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* go-rec-nb-small.c -- nonblocking receive of something smal on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to receive something on a nonblocking channel. */
-
-int
-__go_receive_nonblocking_acquire (struct __go_channel *channel)
-{
- int i;
- _Bool has_data;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_receive)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed
- && (channel->num_entries == 0
- ? channel->next_store == 0
- : channel->next_fetch == channel->next_store))
- {
- __go_unlock_and_notify_selects (channel);
- return RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- }
-
- if (channel->num_entries > 0)
- has_data = channel->next_fetch != channel->next_store;
- else
- {
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is already waiting for data on this
- channel, so we can't pick it up. */
- has_data = 0;
- }
- else if (channel->next_store > 0)
- {
- /* There is data on the channel. */
- has_data = 1;
- }
- else if (__go_synch_with_select (channel, 0))
- {
- /* We synched up with a select sending data, so there will
- be data for us shortly. Tell the select to go, and then
- wait for the data. */
- __go_broadcast_to_select (channel);
-
- while (channel->next_store == 0)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- has_data = 1;
- }
- else
- {
- /* Otherwise there is no data. */
- has_data = 0;
- }
-
- if (has_data)
- {
- channel->waiting_to_receive = 1;
- __go_assert (channel->next_store == 1);
- }
- }
-
- if (!has_data)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- return RECEIVE_NONBLOCKING_ACQUIRE_NODATA;
- }
-
- return RECEIVE_NONBLOCKING_ACQUIRE_DATA;
-}
-
-/* Receive something 64 bits or smaller on a nonblocking channel. */
-
-struct __go_receive_nonblocking_small
-__go_receive_nonblocking_small (struct __go_channel *channel)
-{
- uintptr_t element_size;
- struct __go_receive_nonblocking_small ret;
-
- if (channel == NULL)
- {
- ret.__val = 0;
- ret.__success = 0;
- ret.__closed = 0;
- return ret;
- }
-
- element_size = channel->element_type->__size;
- __go_assert (element_size <= sizeof (uint64_t));
-
- int data = __go_receive_nonblocking_acquire (channel);
- if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
- {
- ret.__val = 0;
- ret.__success = 0;
- ret.__closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- return ret;
- }
-
- ret.__val = channel->data[channel->next_fetch];
-
- __go_receive_release (channel);
-
- ret.__success = 1;
- ret.__closed = 0;
-
- return ret;
-}
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
deleted file mode 100644
index f26dbcdd993..00000000000
--- a/libgo/runtime/go-rec-small.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* go-rec-small.c -- receive something smaller than 64 bits on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* This mutex controls access to the selected field of struct
- __go_channel_select. While this mutex is held, no other mutexes
- may be acquired. */
-
-pthread_mutex_t __go_select_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Try to synchronize with a select waiting on a sychronized channel.
- This is used by a send or receive. The channel is locked. This
- returns true if it was able to synch. */
-
-_Bool
-__go_synch_with_select (struct __go_channel *channel, _Bool is_send)
-{
- struct __go_channel_select *p;
- int i;
-
- __go_assert (channel->num_entries == 0);
-
- i = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (i == 0);
-
- for (p = (is_send
- ? channel->select_receive_queue
- : channel->select_send_queue);
- p != NULL;
- p = p->next)
- {
- if (*p->selected == NULL)
- {
- *p->selected = channel;
- *p->is_read = !is_send;
- if (is_send)
- channel->selected_for_receive = 1;
- else
- channel->selected_for_send = 1;
- break;
- }
- }
-
- i = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (i == 0);
-
- /* The caller is responsible for signalling the select condition
- variable so that the other select knows that something has
- changed. We can't signal it here because we can't acquire the
- select mutex while we hold a channel lock. */
-
- return p != NULL;
-}
-
-/* If we synch with a select, then we need to signal the select that
- something has changed. This requires grabbing the select mutex,
- which can only be done when the channel is unlocked. This routine
- does the signalling. It is called with the channel locked. It
- unlocks the channel, broadcasts the signal and relocks the
- channel. */
-
-void
-__go_broadcast_to_select (struct __go_channel *channel)
-{
- pthread_mutex_t *select_mutex;
- pthread_cond_t *select_cond;
- int i;
-
- select_mutex = channel->select_mutex;
- select_cond = channel->select_cond;
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- __go_assert (select_mutex != NULL && select_cond != NULL);
-
- i = pthread_mutex_lock (select_mutex);
- __go_assert (i == 0);
-
- i = pthread_cond_broadcast (select_cond);
- __go_assert (i == 0);
-
- i = pthread_mutex_unlock (select_mutex);
- __go_assert (i == 0);
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-}
-
-/* Prepare to receive something on a channel. Return true if the
- channel is acquired (which implies that there is data available),
- false if it is closed. */
-
-_Bool
-__go_receive_acquire (struct __go_channel *channel, _Bool for_select)
-{
- int i;
- _Bool my_wait_lock;
- _Bool synched_with_select;
-
- my_wait_lock = 0;
- synched_with_select = 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (1)
- {
- _Bool need_broadcast;
-
- need_broadcast = 0;
-
- /* Check whether the channel is closed. */
- if (channel->is_closed
- && (channel->num_entries == 0
- ? channel->next_store == 0
- : channel->next_fetch == channel->next_store))
- {
- channel->selected_for_receive = 0;
- __go_unlock_and_notify_selects (channel);
- return 0;
- }
-
- /* If somebody else has the channel locked for receiving, we
- have to wait. If FOR_SELECT is true, then we are the one
- with the lock. */
- if (!channel->selected_for_receive || for_select)
- {
- if (channel->num_entries == 0)
- {
- /* If somebody else is waiting to receive, we have to
- wait. */
- if (!channel->waiting_to_receive || my_wait_lock)
- {
- _Bool was_marked;
-
- /* Lock the channel so that we get to receive
- next. */
- was_marked = channel->waiting_to_receive;
- channel->waiting_to_receive = 1;
- my_wait_lock = 1;
-
- /* See if there is a value to receive. */
- if (channel->next_store > 0)
- return 1;
-
- /* If we haven't already done so, try to synch with
- a select waiting to send on this channel. If we
- have already synched with a select, we are just
- looping until the select eventually causes
- something to be sent. */
- if (!synched_with_select && !for_select)
- {
- if (__go_synch_with_select (channel, 0))
- {
- synched_with_select = 1;
- need_broadcast = 1;
- }
- }
-
- /* If we marked the channel as waiting, we need to
- signal, because something changed. It needs to
- be a broadcast since there might be other
- receivers waiting. */
- if (!was_marked)
- {
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
- }
- }
- }
- else
- {
- /* If there is a value on the channel, we are OK. */
- if (channel->next_fetch != channel->next_store)
- return 1;
- }
- }
-
- /* If we just synched with a select, then we need to signal the
- select condition variable. We can only do that if we unlock
- the channel. So we need to unlock, signal, lock, and go
- around the loop again without waiting. */
- if (need_broadcast)
- {
- __go_broadcast_to_select (channel);
- continue;
- }
-
- /* Wait for something to change, then loop around and try
- again. */
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-}
-
-/* Finished receiving something on a channel. */
-
-void
-__go_receive_release (struct __go_channel *channel)
-{
- int i;
-
- if (channel->num_entries != 0)
- channel->next_fetch = (channel->next_fetch + 1) % channel->num_entries;
- else
- {
- /* For a synchronous receiver, we tell the sender that we picked
- up the value by setting the next_store field back to 0.
- Using the mutexes should implement a memory barrier. */
- __go_assert (channel->next_store == 1);
- channel->next_store = 0;
-
- channel->waiting_to_receive = 0;
- }
-
- channel->selected_for_receive = 0;
-
- /* This is a broadcast to make sure that a synchronous sender sees
- it. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- __go_unlock_and_notify_selects (channel);
-}
-
-/* Unlock a channel and notify any waiting selects that something
- happened. */
-
-void
-__go_unlock_and_notify_selects (struct __go_channel *channel)
-{
- pthread_mutex_t* select_mutex;
- pthread_cond_t* select_cond;
- int i;
-
- select_mutex = channel->select_mutex;
- select_cond = channel->select_cond;
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- if (select_mutex != NULL)
- {
- i = pthread_mutex_lock (select_mutex);
- __go_assert (i == 0);
- i = pthread_cond_broadcast (select_cond);
- __go_assert (i == 0);
- i = pthread_mutex_unlock (select_mutex);
- __go_assert (i == 0);
- }
-}
-
-/* Receive something 64 bits or smaller on a channel. */
-
-uint64_t
-__go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
- _Bool *received)
-{
- uintptr_t element_size;
- uint64_t ret;
-
- if (channel == NULL)
- {
- /* Block forever. */
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- __go_assert (element_size <= sizeof (uint64_t));
-
- if (!__go_receive_acquire (channel, for_select))
- {
- 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);
-}
diff --git a/libgo/runtime/go-reflect-chan.c b/libgo/runtime/go-reflect-chan.c
deleted file mode 100644
index 6f6693b6b54..00000000000
--- a/libgo/runtime/go-reflect-chan.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* go-reflect-chan.c -- channel reflection support for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdlib.h>
-#include <stdint.h>
-
-#include "config.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "go-type.h"
-#include "channel.h"
-
-/* This file implements support for reflection on channels. These
- functions are called from reflect/value.go. */
-
-extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t)
- asm ("libgo_reflect.reflect.makechan");
-
-uintptr_t
-makechan (const struct __go_type_descriptor *typ, uint32_t size)
-{
- struct __go_channel *channel;
- void *ret;
-
- channel = __go_new_channel (typ, size);
-
- ret = __go_alloc (sizeof (void *));
- __builtin_memcpy (ret, &channel, sizeof (void *));
- return (uintptr_t) ret;
-}
-
-extern _Bool chansend (struct __go_channel_type *, uintptr_t, uintptr_t, _Bool)
- asm ("libgo_reflect.reflect.chansend");
-
-_Bool
-chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
- _Bool nb)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
- uintptr_t element_size;
- void *pv;
-
- __go_assert (ct->__common.__code == GO_CHAN);
-
- if (__go_is_pointer_type (ct->__element_type))
- pv = &val_i;
- else
- pv = (void *) val_i;
-
- element_size = ct->__element_type->__size;
- if (element_size <= sizeof (uint64_t))
- {
- union
- {
- char b[sizeof (uint64_t)];
- uint64_t v;
- } u;
-
- __builtin_memset (u.b, 0, sizeof (uint64_t));
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (u.b, pv, element_size);
-#else
- __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv,
- element_size);
-#endif
- if (nb)
- return __go_send_nonblocking_small (channel, u.v);
- else
- {
- __go_send_small (channel, u.v, 0);
- return 1;
- }
- }
- else
- {
- if (nb)
- return __go_send_nonblocking_big (channel, pv);
- else
- {
- __go_send_big (channel, pv, 0);
- return 1;
- }
- }
-}
-
-struct chanrecv_ret
-{
- uintptr_t val;
- _Bool selected;
- _Bool received;
-};
-
-extern struct chanrecv_ret chanrecv (struct __go_channel_type *, uintptr_t,
- _Bool)
- asm ("libgo_reflect.reflect.chanrecv");
-
-struct chanrecv_ret
-chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
- void *pv;
- uintptr_t element_size;
- struct chanrecv_ret ret;
-
- __go_assert (ct->__common.__code == GO_CHAN);
-
- element_size = ct->__element_type->__size;
-
- if (__go_is_pointer_type (ct->__element_type))
- pv = &ret.val;
- else
- {
- pv = __go_alloc (element_size);
- ret.val = (uintptr_t) pv;
- }
-
- if (element_size <= sizeof (uint64_t))
- {
- union
- {
- char b[sizeof (uint64_t)];
- uint64_t v;
- } u;
-
- if (!nb)
- {
- u.v = __go_receive_small_closed (channel, 0, &ret.received);
- ret.selected = 1;
- }
- else
- {
- struct __go_receive_nonblocking_small s;
-
- s = __go_receive_nonblocking_small (channel);
- ret.selected = s.__success || s.__closed;
- ret.received = s.__success;
- u.v = s.__val;
- }
-
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (pv, u.b, element_size);
-#else
- __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size,
- element_size);
-#endif
- }
- else
- {
- if (!nb)
- {
- ret.received = __go_receive_big (channel, pv, 0);
- ret.selected = 1;
- }
- else
- {
- _Bool got;
- _Bool closed;
-
- got = __go_receive_nonblocking_big (channel, pv, &closed);
- ret.selected = got || closed;
- ret.received = got;
- }
- }
-
- return ret;
-}
-
-extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose");
-
-void
-chanclose (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- __go_builtin_close (channel);
-}
-
-extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen");
-
-int32_t
-chanlen (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- return (int32_t) __go_chan_len (channel);
-}
-
-extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap");
-
-int32_t
-chancap (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- return (int32_t) __go_chan_cap (channel);
-}
diff --git a/libgo/runtime/go-select.c b/libgo/runtime/go-select.c
deleted file mode 100644
index 677c699b52c..00000000000
--- a/libgo/runtime/go-select.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/* go-select.c -- implement select.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <pthread.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "runtime.h"
-#include "config.h"
-#include "go-assert.h"
-#include "channel.h"
-
-/* __go_select builds an array of these structures. */
-
-struct select_channel
-{
- /* The channel being selected. */
- struct __go_channel* channel;
- /* If this channel is selected, the value to return. */
- uintptr_t retval;
- /* If this channel is a duplicate of one which appears earlier in
- the array, this is the array index of the earlier channel. This
- is -1UL if this is not a dup. */
- uintptr_t dup_index;
- /* An entry to put on the send or receive queue. */
- struct __go_channel_select queue_entry;
- /* True if selected for send. */
- _Bool is_send;
- /* True if channel is ready--it has data to receive or space to
- send. */
- _Bool is_ready;
-};
-
-/* This mutex controls access to __go_select_cond. This mutex may not
- be acquired if any channel locks are held. */
-
-static pthread_mutex_t __go_select_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* When we have to wait for channels, we tell them to trigger this
- condition variable when they send or receive something. */
-
-static pthread_cond_t __go_select_cond = PTHREAD_COND_INITIALIZER;
-
-/* Sort the channels by address. This avoids deadlock when multiple
- selects are running on overlapping sets of channels. */
-
-static int
-channel_sort (const void *p1, const void *p2)
-{
- const struct select_channel *c1 = (const struct select_channel *) p1;
- const struct select_channel *c2 = (const struct select_channel *) p2;
-
- if ((uintptr_t) c1->channel < (uintptr_t) c2->channel)
- return -1;
- else if ((uintptr_t) c1->channel > (uintptr_t) c2->channel)
- return 1;
- else
- return 0;
-}
-
-/* Return whether there is an entry on QUEUE which can be used for a
- synchronous send or receive. */
-
-static _Bool
-is_queue_ready (struct __go_channel_select *queue)
-{
- int x;
-
- if (queue == NULL)
- return 0;
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- while (queue != NULL)
- {
- if (*queue->selected == NULL)
- break;
- queue = queue->next;
- }
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- return queue != NULL;
-}
-
-/* Return whether CHAN is ready. If IS_SEND is true check whether it
- has space to send, otherwise check whether it has a value to
- receive. */
-
-static _Bool
-is_channel_ready (struct __go_channel* channel, _Bool is_send)
-{
- if (is_send)
- {
- if (channel->selected_for_send)
- return 0;
- if (channel->is_closed)
- return 1;
- if (channel->num_entries > 0)
- {
- /* An asynchronous channel is ready for sending if there is
- room in the buffer. */
- return ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch);
- }
- else
- {
- if (channel->waiting_to_send)
- {
- /* Some other goroutine is waiting to send on this
- channel, so we can't. */
- return 0;
- }
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive a value,
- so we can send one. */
- return 1;
- }
- if (is_queue_ready (channel->select_receive_queue))
- {
- /* There is a select statement waiting to synchronize
- with this one. */
- return 1;
- }
- return 0;
- }
- }
- else
- {
- if (channel->selected_for_receive)
- return 0;
- if (channel->is_closed)
- return 1;
- if (channel->num_entries > 0)
- {
- /* An asynchronous channel is ready for receiving if there
- is a value in the buffer. */
- return channel->next_fetch != channel->next_store;
- }
- else
- {
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive from this
- channel, so it is not ready for us to receive. */
- return 0;
- }
- if (channel->next_store > 0)
- {
- /* There is data on the channel. */
- return 1;
- }
- if (is_queue_ready (channel->select_send_queue))
- {
- /* There is a select statement waiting to synchronize
- with this one. */
- return 1;
- }
- return 0;
- }
- }
-}
-
-/* Mark a channel as selected. The channel is locked. IS_SELECTED is
- true if the channel was selected for us by another goroutine. We
- set *NEEDS_BROADCAST if we need to broadcast on the select
- condition variable. Return true if we got it. */
-
-static _Bool
-mark_channel_selected (struct __go_channel *channel, _Bool is_send,
- _Bool is_selected, _Bool *needs_broadcast)
-{
- if (channel->num_entries == 0)
- {
- /* This is a synchronous channel. If there is no goroutine
- currently waiting, but there is another select waiting, then
- we need to tell that select to use this channel. That may
- fail--there may be no other goroutines currently waiting--as
- a third goroutine may already have claimed the select. */
- if (!is_selected
- && !channel->is_closed
- && (is_send
- ? !channel->waiting_to_receive
- : channel->next_store == 0))
- {
- int x;
- struct __go_channel_select *queue;
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- queue = (is_send
- ? channel->select_receive_queue
- : channel->select_send_queue);
- __go_assert (queue != NULL);
-
- while (queue != NULL)
- {
- if (*queue->selected == NULL)
- {
- *queue->selected = channel;
- *queue->is_read = !is_send;
- break;
- }
- queue = queue->next;
- }
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- if (queue == NULL)
- return 0;
-
- if (is_send)
- channel->selected_for_receive = 1;
- else
- channel->selected_for_send = 1;
-
- /* We are going to have to tell the other select that there
- is something to do. */
- *needs_broadcast = 1;
- }
- }
-
- if (is_send)
- channel->selected_for_send = 1;
- else
- channel->selected_for_receive = 1;
-
- return 1;
-}
-
-/* Mark a channel to indicate that a select is waiting. The channel
- is locked. */
-
-static void
-mark_select_waiting (struct select_channel *sc,
- struct __go_channel **selected_pointer,
- _Bool *selected_for_read_pointer)
-{
- struct __go_channel *channel = sc->channel;
- _Bool is_send = sc->is_send;
-
- if (channel->num_entries == 0)
- {
- struct __go_channel_select **pp;
-
- pp = (is_send
- ? &channel->select_send_queue
- : &channel->select_receive_queue);
-
- /* Add an entry to the queue of selects on this channel. */
- sc->queue_entry.next = *pp;
- sc->queue_entry.selected = selected_pointer;
- sc->queue_entry.is_read = selected_for_read_pointer;
-
- *pp = &sc->queue_entry;
- }
-
- channel->select_mutex = &__go_select_mutex;
- channel->select_cond = &__go_select_cond;
-
- /* We never actually clear the select_mutex and select_cond fields.
- In order to clear them safely, we would need to have some way of
- knowing when no select is waiting for the channel. Thus we
- introduce a bit of inefficiency for every channel that select
- needs to wait for. This is harmless other than the performance
- cost. */
-}
-
-/* Remove the entry for this select waiting on this channel. The
- channel is locked. We check both queues, because the channel may
- be selected for both reading and writing. */
-
-static void
-clear_select_waiting (struct select_channel *sc,
- struct __go_channel **selected_pointer)
-{
- struct __go_channel *channel = sc->channel;
-
- if (channel->num_entries == 0)
- {
- _Bool found;
- struct __go_channel_select **pp;
-
- found = 0;
-
- for (pp = &channel->select_send_queue; *pp != NULL; pp = &(*pp)->next)
- {
- if ((*pp)->selected == selected_pointer)
- {
- *pp = (*pp)->next;
- found = 1;
- break;
- }
- }
-
- for (pp = &channel->select_receive_queue; *pp != NULL; pp = &(*pp)->next)
- {
- if ((*pp)->selected == selected_pointer)
- {
- *pp = (*pp)->next;
- found = 1;
- break;
- }
- }
-
- __go_assert (found);
- }
-}
-
-/* Look through the list of channels to see which ones are ready.
- Lock each channels, and set the is_ready flag. Return the number
- of ready channels. */
-
-static uintptr_t
-lock_channels_find_ready (struct select_channel *channels, uintptr_t count)
-{
- uintptr_t ready_count;
- uintptr_t i;
-
- ready_count = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
- uintptr_t dup_index = channels[i].dup_index;
- int x;
-
- if (channel == NULL)
- continue;
-
- if (dup_index != (uintptr_t) -1UL)
- {
- if (channels[dup_index].is_ready)
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- continue;
- }
-
- x = pthread_mutex_lock (&channel->lock);
- __go_assert (x == 0);
-
- if (is_channel_ready (channel, is_send))
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- }
-
- return ready_count;
-}
-
-/* The channel we are going to select has been forced by some other
- goroutine. SELECTED_CHANNEL is the channel we will use,
- SELECTED_FOR_READ is whether the other goroutine wants to read from
- the channel. Note that the channel could be specified multiple
- times in this select, so we must mark each appropriate entry for
- this channel as ready. Every other channel is marked as not ready.
- All the channels are locked before this routine is called. This
- returns the number of ready channels. */
-
-uintptr_t
-force_selected_channel_ready (struct select_channel *channels, uintptr_t count,
- struct __go_channel *selected_channel,
- _Bool selected_for_read)
-{
- uintptr_t ready_count;
- uintptr_t i;
-
- ready_count = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channel != selected_channel
- || (is_send ? !selected_for_read : selected_for_read))
- channels[i].is_ready = 0;
- else
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- }
- __go_assert (ready_count > 0);
- return ready_count;
-}
-
-/* Unlock all the channels. */
-
-static void
-unlock_channels (struct select_channel *channels, uintptr_t count)
-{
- uintptr_t i;
- int x;
-
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
-
- if (channel == NULL)
- continue;
-
- if (channels[i].dup_index != (uintptr_t) -1UL)
- continue;
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
-}
-
-/* At least one channel is ready. Randomly pick a channel to return.
- Unlock all the channels. IS_SELECTED is true if the channel was
- picked for us by some other goroutine. If SELECTED_POINTER is not
- NULL, remove it from the queue for all the channels. Return the
- retval field of the selected channel. This will return 0 if we
- can't use the selected channel, because it relied on synchronizing
- with some other select, and that select already synchronized with a
- different channel. */
-
-static uintptr_t
-unlock_channels_and_select (struct select_channel *channels,
- uintptr_t count, uintptr_t ready_count,
- _Bool is_selected,
- struct __go_channel **selected_pointer)
-{
- uintptr_t selected;
- uintptr_t ret;
- _Bool needs_broadcast;
- uintptr_t i;
- int x;
-
- /* Pick which channel we are going to return. */
-#if defined(HAVE_RANDOM)
- selected = (uintptr_t) random () % ready_count;
-#else
- selected = (uintptr_t) rand () % ready_count;
-#endif
- ret = 0;
- needs_broadcast = 0;
-
- /* Look at the channels in reverse order so that we don't unlock a
- duplicated channel until we have seen all its dups. */
- for (i = 0; i < count; ++i)
- {
- uintptr_t j = count - i - 1;
- struct __go_channel *channel = channels[j].channel;
- _Bool is_send = channels[j].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channels[j].is_ready)
- {
- if (selected == 0)
- {
- if (mark_channel_selected (channel, is_send, is_selected,
- &needs_broadcast))
- ret = channels[j].retval;
- }
-
- --selected;
- }
-
- if (channels[j].dup_index == (uintptr_t) -1UL)
- {
- if (selected_pointer != NULL)
- clear_select_waiting (&channels[j], selected_pointer);
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
- }
-
- /* The NEEDS_BROADCAST variable is set if we are synchronizing with
- some other select statement. We can't do the actual broadcast
- until we have unlocked all the channels. */
-
- if (needs_broadcast)
- {
- x = pthread_mutex_lock (&__go_select_mutex);
- __go_assert (x == 0);
-
- x = pthread_cond_broadcast (&__go_select_cond);
- __go_assert (x == 0);
-
- x = pthread_mutex_unlock (&__go_select_mutex);
- __go_assert (x == 0);
- }
-
- return ret;
-}
-
-/* Mark all channels to show that we are waiting for them. This is
- called with the select mutex held, but none of the channels are
- locked. This returns true if some channel was found to be
- ready. */
-
-static _Bool
-mark_all_channels_waiting (struct select_channel* channels, uintptr_t count,
- struct __go_channel **selected_pointer,
- _Bool *selected_for_read_pointer)
-{
- _Bool ret;
- int x;
- uintptr_t i;
-
- ret = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channels[i].dup_index != (uintptr_t) -1UL)
- {
- uintptr_t j;
-
- /* A channel may be selected for both read and write. */
- if (channels[channels[i].dup_index].is_send == is_send)
- continue;
- else
- {
- for (j = channels[i].dup_index + 1; j < i; ++j)
- {
- if (channels[j].channel == channel
- && channels[j].is_send == is_send)
- break;
- }
- if (j < i)
- continue;
- }
- }
-
- x = pthread_mutex_lock (&channel->lock);
- __go_assert (x == 0);
-
- /* To avoid a race condition, we have to check again whether the
- channel is ready. It may have become ready since we did the
- first set of checks but before we acquired the select mutex.
- If we don't check here, we could sleep forever on the select
- condition variable. */
- if (is_channel_ready (channel, is_send))
- ret = 1;
-
- /* If SELECTED_POINTER is NULL, then we have already marked the
- channel as waiting. */
- if (selected_pointer != NULL)
- mark_select_waiting (&channels[i], selected_pointer,
- selected_for_read_pointer);
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
-
- return ret;
-}
-
-/* Implement select. This is called by the compiler-generated code
- with pairs of arguments: a pointer to a channel, and an int which
- is non-zero for send, zero for receive. */
-
-uintptr_t
-__go_select (uintptr_t count, _Bool has_default,
- struct __go_channel **channel_args, _Bool *is_send_args)
-{
- struct select_channel stack_buffer[16];
- struct select_channel *allocated_buffer;
- struct select_channel *channels;
- uintptr_t i;
- int x;
- struct __go_channel *selected_channel;
- _Bool selected_for_read;
- _Bool is_queued;
-
- if (count < sizeof stack_buffer / sizeof stack_buffer[0])
- {
- channels = &stack_buffer[0];
- allocated_buffer = NULL;
- }
- else
- {
- allocated_buffer = ((struct select_channel *)
- malloc (count * sizeof (struct select_channel)));
- channels = allocated_buffer;
- }
-
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel_arg = channel_args[i];
- _Bool is_send = is_send_args[i];
-
- channels[i].channel = (struct __go_channel*) channel_arg;
- channels[i].retval = i + 1;
- channels[i].dup_index = (uintptr_t) -1UL;
- channels[i].queue_entry.next = NULL;
- channels[i].queue_entry.selected = NULL;
- channels[i].is_send = is_send;
- channels[i].is_ready = 0;
- }
-
- qsort (channels, count, sizeof (struct select_channel), channel_sort);
-
- for (i = 0; i < count; ++i)
- {
- uintptr_t j;
-
- for (j = 0; j < i; ++j)
- {
- if (channels[j].channel == channels[i].channel)
- {
- channels[i].dup_index = j;
- break;
- }
- }
- }
-
- /* SELECT_CHANNEL is used to select synchronized channels. If no
- channels are ready, we store a pointer to this variable on the
- select queue for each synchronized channel. Because the variable
- may be set by channel operations running in other goroutines,
- SELECT_CHANNEL may only be accessed when all the channels are
- locked and/or when the select_data_mutex is locked. */
- selected_channel = NULL;
-
- /* SELECTED_FOR_READ is set to true if SELECTED_CHANNEL was set by a
- goroutine which wants to read from the channel. The access
- restrictions for this are like those for SELECTED_CHANNEL. */
- selected_for_read = 0;
-
- /* IS_QUEUED is true if we have queued up this select on the queues
- for any associated synchronous channels. We only do this if no
- channels are ready the first time around the loop. */
- is_queued = 0;
-
- while (1)
- {
- int ready_count;
- _Bool is_selected;
-
- /* Lock all channels, identify which ones are ready. */
- ready_count = lock_channels_find_ready (channels, count);
-
- /* All the channels are locked, so we can look at
- SELECTED_CHANNEL. If it is not NULL, then our choice has
- been forced by some other goroutine. This can only happen
- after the first time through the loop. */
- is_selected = selected_channel != NULL;
- if (is_selected)
- ready_count = force_selected_channel_ready (channels, count,
- selected_channel,
- selected_for_read);
-
- if (ready_count > 0)
- {
- uintptr_t ret;
-
- ret = unlock_channels_and_select (channels, count, ready_count,
- is_selected,
- (is_queued
- ? &selected_channel
- : NULL));
-
- /* If RET is zero, it means that the channel we picked
- turned out not to be ready, because some other select
- grabbed it during our traversal. Loop around and try
- again. */
- if (ret == 0)
- {
- is_queued = 0;
- /* We are no longer on any channel queues, so it is safe
- to touch SELECTED_CHANNEL here. It must be NULL,
- because otherwise that would somebody has promised to
- synch up with us and then failed to do so. */
- __go_assert (selected_channel == NULL);
- continue;
- }
-
- if (allocated_buffer != NULL)
- free (allocated_buffer);
-
- return ret;
- }
-
- /* No channels were ready. */
-
- unlock_channels (channels, count);
-
- if (has_default)
- {
- /* Use the default clause. */
- if (allocated_buffer != NULL)
- free (allocated_buffer);
- return 0;
- }
-
- /* This is a blocking select. Grab the select lock, tell all
- the channels to notify us when something happens, and wait
- for something to happen. */
-
- x = pthread_mutex_lock (&__go_select_mutex);
- __go_assert (x == 0);
-
- /* Check whether CHANNEL_SELECTED was set while the channels
- were unlocked. If it was set, then we can simply loop around
- again. We need to check this while the select mutex is held.
- It is possible that something will set CHANNEL_SELECTED while
- we mark the channels as waiting. If this happens, that
- goroutine is required to signal the select condition
- variable, which means acquiring the select mutex. Since we
- have the select mutex locked ourselves, we can not miss that
- signal. */
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- is_selected = selected_channel != NULL;
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- if (!is_selected)
- {
- /* Mark the channels as waiting, and check whether they have
- become ready. */
- if (!mark_all_channels_waiting (channels, count,
- (is_queued
- ? NULL
- : &selected_channel),
- (is_queued
- ? NULL
- : &selected_for_read)))
- runtime_cond_wait (&__go_select_cond, &__go_select_mutex);
-
- is_queued = 1;
- }
-
- x = pthread_mutex_unlock (&__go_select_mutex);
- __go_assert (x == 0);
- }
-}
diff --git a/libgo/runtime/go-send-big.c b/libgo/runtime/go-send-big.c
deleted file mode 100644
index 61d4a0f13d9..00000000000
--- a/libgo/runtime/go-send-big.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* go-send-big.c -- send something bigger than uint64_t on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "go-panic.h"
-#include "channel.h"
-
-void
-__go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- // Block forever.
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- __go_send_acquire (channel, for_select);
-
- offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, element_size);
-
- __go_send_release (channel);
-}
diff --git a/libgo/runtime/go-send-nb-big.c b/libgo/runtime/go-send-nb-big.c
deleted file mode 100644
index e039874ef9a..00000000000
--- a/libgo/runtime/go-send-nb-big.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* go-send-nb-big.c -- nonblocking send of something big on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "channel.h"
-
-_Bool
-__go_send_nonblocking_big (struct __go_channel* channel, const void *val)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- return 0;
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- if (!__go_send_nonblocking_acquire (channel))
- return 0;
-
- offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, element_size);
-
- __go_send_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
deleted file mode 100644
index c77ee9183e2..00000000000
--- a/libgo/runtime/go-send-nb-small.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* go-send-nb-small.c -- nonblocking send of something small on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to send something on a nonblocking channel. Return true if
- we acquired the channel, false if we did not acquire it because
- there is no space to send a value. */
-
-_Bool
-__go_send_nonblocking_acquire (struct __go_channel *channel)
-{
- int i;
- _Bool has_space;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_send)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("send on closed channel");
- }
-
- if (channel->num_entries > 0)
- has_space = ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch);
- else
- {
- /* This is a synchronous channel. If somebody is current
- sending, then we can't send. Otherwise, see if somebody is
- waiting to receive, or see if we can synch with a select. */
- if (channel->waiting_to_send)
- {
- /* Some other goroutine is currently sending on this
- channel, which means that we can't. */
- has_space = 0;
- }
- else if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive a value, so we
- can send directly to them. */
- has_space = 1;
- }
- else if (__go_synch_with_select (channel, 1))
- {
- /* We found a select waiting to receive data, so we can send
- to that. */
- __go_broadcast_to_select (channel);
- has_space = 1;
- }
- else
- {
- /* Otherwise, we can't send, because nobody is waiting to
- receive. */
- has_space = 0;
- }
-
- if (has_space)
- {
- channel->waiting_to_send = 1;
- __go_assert (channel->next_store == 0);
- }
- }
-
- if (!has_space)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return 0;
- }
-
- return 1;
-}
-
-/* Send something 64 bits or smaller on a channel. */
-
-_Bool
-__go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
-{
- if (channel == NULL)
- return 0;
-
- __go_assert (channel->element_type->__size <= sizeof (uint64_t));
-
- if (!__go_send_nonblocking_acquire (channel))
- return 0;
-
- channel->data[channel->next_store] = val;
-
- __go_send_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
deleted file mode 100644
index 06bcb41b9ad..00000000000
--- a/libgo/runtime/go-send-small.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* go-send-small.c -- send something 64 bits or smaller on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to send something on a channel. FOR_SELECT is true if this
- call is being made after a select statement returned with this
- channel selected. */
-
-void
-__go_send_acquire (struct __go_channel *channel, _Bool for_select)
-{
- int i;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (1)
- {
- if (channel->is_closed)
- {
- if (for_select)
- channel->selected_for_send = 0;
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("send on closed channel");
- }
-
- /* If somebody else has the channel locked for sending, we have
- to wait. If FOR_SELECT is true, then we are the one with the
- lock. */
- if (!channel->selected_for_send || for_select)
- {
- if (channel->num_entries == 0)
- {
- /* This is a synchronous channel. If nobody else is
- waiting to send, we grab the channel and tell the
- caller to send the data. We will then wait for a
- receiver. */
- if (!channel->waiting_to_send)
- {
- __go_assert (channel->next_store == 0);
- return;
- }
- }
- else
- {
- /* If there is room on the channel, we are OK. */
- if ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch)
- return;
- }
- }
-
- /* Wait for something to change, then loop around and try
- again. */
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-}
-
-/* Finished sending something on a channel. */
-
-void
-__go_send_release (struct __go_channel *channel)
-{
- int i;
-
- if (channel->num_entries != 0)
- {
- /* This is a buffered channel. Bump the store count and signal
- the condition variable. */
- channel->next_store = (channel->next_store + 1) % channel->num_entries;
-
- i = pthread_cond_signal (&channel->cond);
- __go_assert (i == 0);
- }
- else
- {
- _Bool synched_with_select;
-
- /* This is a synchronous channel. Indicate that we have a value
- waiting. */
- channel->next_store = 1;
- channel->waiting_to_send = 1;
-
- /* Tell everybody else to do something. This has to be a
- broadcast because we might have both senders and receivers
- waiting on the condition, but senders won't send another
- signal. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- /* Wait until the value is received. */
- synched_with_select = 0;
- while (1)
- {
- if (channel->next_store == 0)
- break;
-
- /* If nobody is currently waiting to receive, try to synch
- up with a select. */
- if (!channel->waiting_to_receive && !synched_with_select)
- {
- if (__go_synch_with_select (channel, 1))
- {
- synched_with_select = 1;
- __go_broadcast_to_select (channel);
- continue;
- }
- }
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-
- channel->waiting_to_send = 0;
-
- /* Using the mutexes should implement a memory barrier. */
-
- /* We have to signal again since we cleared the waiting_to_send
- field. This has to be a broadcast because both senders and
- receivers might be waiting, but only senders will be able to
- act. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
- }
-
- channel->selected_for_send = 0;
-
- __go_unlock_and_notify_selects (channel);
-}
-
-/* Send something 64 bits or smaller on a channel. */
-
-void
-__go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
-{
- if (channel == NULL)
- {
- // Block forever.
- __go_select (0, 0, NULL, NULL);
- }
-
- __go_assert (channel->element_type->__size <= sizeof (uint64_t));
-
- __go_send_acquire (channel, for_select);
-
- channel->data[channel->next_store] = val;
-
- __go_send_release (channel);
-}
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index 958b421c871..cd165f45112 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -218,7 +218,7 @@ sighandler (int sig)
/* Ignore a signal. */
static void
-sigignore (int sig __attribute__ ((unused)))
+sig_ignore (int sig __attribute__ ((unused)))
{
}
@@ -247,7 +247,7 @@ runtime_initsig (int32 queue)
if (signals[i].catch || signals[i].queue)
sa.sa_handler = sighandler;
else
- sa.sa_handler = sigignore;
+ sa.sa_handler = sig_ignore;
sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
if (sigaction (signals[i].sig, &sa, NULL) != 0)
__go_assert (0);
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 9455ae88c5a..e28bc82f8ab 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -55,14 +55,15 @@ typedef struct M M;
typedef union Note Note;
typedef struct MCache MCache;
typedef struct FixAlloc FixAlloc;
+typedef struct Hchan Hchan;
-typedef struct __go_defer_stack Defer;
+typedef struct __go_open_array Slice;
+typedef struct __go_string String;
typedef struct __go_interface Iface;
typedef struct __go_empty_interface Eface;
typedef struct __go_type_descriptor Type;
+typedef struct __go_defer_stack Defer;
typedef struct __go_panic_stack Panic;
-typedef struct __go_open_array Slice;
-typedef struct __go_string String;
typedef struct __go_func_type FuncType;
typedef struct __go_map_type MapType;
@@ -131,6 +132,7 @@ struct G
bool fromgogo; // reached from gogo
int16 status;
int32 goid;
+ uint32 selgen; // valid sudog pointer
const char* waitreason; // if status==Gwaiting
G* schedlink;
bool readyonstop;
@@ -335,6 +337,3 @@ void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
#ifdef __rtems__
void __wrap_rtems_task_variable_add(void **);
#endif
-
-/* Temporary. */
-void runtime_cond_wait(pthread_cond_t*, pthread_mutex_t*);
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index 459fc85c780..d43e224ffb2 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -90,27 +90,3 @@ runtime_minit(void)
if(sigaltstack(&ss, nil) < 0)
*(int *)0xf1 = 0xf1;
}
-
-// Temporary functions, which will be removed when we stop using
-// condition variables.
-
-void
-runtime_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
-{
- int i;
-
- runtime_entersyscall();
-
- i = pthread_cond_wait(cond, mutex);
- if(i != 0)
- runtime_throw("pthread_cond_wait");
- i = pthread_mutex_unlock(mutex);
- if(i != 0)
- runtime_throw("pthread_mutex_unlock");
-
- runtime_exitsyscall();
-
- i = pthread_mutex_lock(mutex);
- if(i != 0)
- runtime_throw("pthread_mutex_lock");
-}