{"id":813704,"url":"http://patchwork.ozlabs.org/api/patches/813704/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/CAOyqgcV4dS9waWygmSE5LACpyizxxOnR-Y9aXQ1VXYz8J5oDsA@mail.gmail.com/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<CAOyqgcV4dS9waWygmSE5LACpyizxxOnR-Y9aXQ1VXYz8J5oDsA@mail.gmail.com>","list_archive_url":null,"date":"2017-09-14T03:57:20","name":"Go patch committed: simplify select and channel operations","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"797d7207ecb3795d82821816a55574e090492608","submitter":{"id":36501,"url":"http://patchwork.ozlabs.org/api/people/36501/?format=json","name":"Ian Lance Taylor","email":"iant@golang.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/CAOyqgcV4dS9waWygmSE5LACpyizxxOnR-Y9aXQ1VXYz8J5oDsA@mail.gmail.com/mbox/","series":[{"id":3026,"url":"http://patchwork.ozlabs.org/api/series/3026/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=3026","date":"2017-09-14T03:57:20","name":"Go patch committed: simplify select and channel operations","version":1,"mbox":"http://patchwork.ozlabs.org/series/3026/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/813704/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/813704/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-return-462103-incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","mailing list gcc-patches@gcc.gnu.org"],"Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-462103-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"I4SlLgyk\"; dkim-atps=neutral","sourceware.org; auth=none"],"Received":["from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xt4Vt2FMXz9sBZ\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 13:57:41 +1000 (AEST)","(qmail 7020 invoked by alias); 14 Sep 2017 03:57:28 -0000","(qmail 3917 invoked by uid 89); 14 Sep 2017 03:57:27 -0000","from mail-pg0-f53.google.com (HELO mail-pg0-f53.google.com)\n\t(74.125.83.53) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tThu, 14 Sep 2017 03:57:22 +0000","by mail-pg0-f53.google.com with SMTP id i130so4199175pgc.3 for\n\t<gcc-patches@gcc.gnu.org>; Wed, 13 Sep 2017 20:57:22 -0700 (PDT)","by 10.100.182.173 with HTTP; Wed, 13 Sep 2017 20:57:20 -0700 (PDT)"],"DomainKey-Signature":"a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; q=\n\tdns; s=default; b=vIE8sSuugNOIM5epSJlf9D5qWztif7BQ9f3U1+aJ2ZFrpp\n\t8nkttXHResItqI+m6OBlHFoSLkZLMsCUS6beyMmGfx+pHr6JdkZR0sJGWLoPWoUs\n\tILN1dDtvi+3tGlZu3gTgzXwTUx8DbLdd0E/5BKR0Gd6js+ma5Tq/QozFK1kXI=","DKIM-Signature":"v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender\n\t:mime-version:from:date:message-id:subject:to:content-type; s=\n\tdefault; bh=svJojSMd4qtJBQfrD0ZrolemFpY=; b=I4SlLgykoTGuRwtScHl9\n\tZJMGY2rOYql3HwwGjS/rL/Z64ODVjpUAkwOMyUwfZd7v1tHwEK6PhPn4SmQ4AOjZ\n\tDrtTyt/aIRMAhf5qrx+hKqqiFb20xjopKmJkc9p2Zco9C/DHhvk0uPXdmP7G0i5l\n\tnR+UqQZssybW5SQHOMAcuOc=","Mailing-List":"contact gcc-patches-help@gcc.gnu.org; run by ezmlm","Precedence":"bulk","List-Id":"<gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>","List-Archive":"<http://gcc.gnu.org/ml/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-help@gcc.gnu.org>","Sender":"gcc-patches-owner@gcc.gnu.org","X-Virus-Found":"No","X-Spam-SWARE-Status":"No, score=-15.5 required=5.0 tests=AWL, BAYES_00,\n\tGIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS,\n\tRCVD_IN_DNSWL_NONE,\n\tSPF_PASS autolearn=ham version=3.3.2 spammy=8888, kc,\n\tStatement, compete","X-HELO":"mail-pg0-f53.google.com","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net;\n\ts=20161025;\n\th=x-gm-message-state:mime-version:from:date:message-id:subject:to;\n\tbh=OA5Hrs1OALvHLLUclamtzABvKLx3cTAkuhW/i8zIOmg=;\n\tb=ec1YFl5YggR5V3xJIp2JmczWG5HzOtxlYwnwgJMWWvq2Vbw09yI/taT0vz6dm75Oky\n\to/0j7dJ5A1ppATPNgMGPCxA6/2aHWFuS3HuyTQf2/nAxmAeM7dtk4lelFB38kWy5cITz\n\tFg5skeldgXxy0r7ZfNPFRIEVYLp/dCSelS+WWn0fQ5EUB7EL/hgjQGw8drrLs368sNaj\n\tpmxxkkj8TSnWYqY7pAqAI5m3iQhBnZv4Vto90e8m2nILJhMUB87IzPAhWSQBcNa1Nm4o\n\t4vWrKe4sc8VP3srLHx/IbulsOeWJB6DVOm4hQw5p0DZs6aBON9PN/z//Pzk8tOC6JIRz\n\taQ6A==","X-Gm-Message-State":"AHPjjUh3APZGAdxH08n0/df8dEjygHNR54lfuCWtLi8brMGjwgL3ErJa\tYrrTdKWu2ngCoTOZKxQLZ1V3mQXKQ0m3ex7T1aMB5Mtr","X-Google-Smtp-Source":"ADKCNb7I1ZRKupFQbiuAEUH91DbHFOypiwXsFFunBFK6DeYnjHkaf5NzytnqDzkJnFc0LyuNypolX0Gab1kIN/2fkug=","X-Received":"by 10.101.71.135 with SMTP id e7mr20279949pgs.112.1505361440926;\n\tWed, 13 Sep 2017 20:57:20 -0700 (PDT)","MIME-Version":"1.0","From":"Ian Lance Taylor <iant@golang.org>","Date":"Wed, 13 Sep 2017 20:57:20 -0700","Message-ID":"<CAOyqgcV4dS9waWygmSE5LACpyizxxOnR-Y9aXQ1VXYz8J5oDsA@mail.gmail.com>","Subject":"Go patch committed: simplify select and channel operations","To":"gcc-patches <gcc-patches@gcc.gnu.org>,\n\t\"gofrontend-dev@googlegroups.com\" <gofrontend-dev@googlegroups.com>","Content-Type":"multipart/mixed; boundary=\"089e0826fc44f2500d05591e45c2\""},"content":"In preparation for upgrading libgo to the 1.9 release, this patch to\nthe Go frontend approximately incorporates https://golang.org/cl/37661\nand\nhttps://golang.org/cl/38351 from the gc toolchain.\n\nCL 37661 changed the gc compiler such that the select statement simply\nreturns an integer which is then used as the argument for a switch.\nSince gccgo already worked that way, this just adjusts the switch code\nto look like the gc switch code by removing the explicit case index\nexpression and calculating it from the order of calls to selectsend,\nselectrecv, and selectdefault.\n\nCL 38351 simplifies the channel code by not passing the unused channel\ntype descriptor pointer.\n\nBootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed\nto mainline.\n\nIan","diff":"Index: gcc/go/gofrontend/MERGE\n===================================================================\n--- gcc/go/gofrontend/MERGE\t(revision 252748)\n+++ gcc/go/gofrontend/MERGE\t(working copy)\n@@ -1,4 +1,4 @@\n-0176cbc6dbd2170bfe2eb8904b80ddfe4c946997\n+199f175f4239d1ca6d7e80d08639955d41c3b09f\n \n The first line of this file holds the git revision number of the last\n merge done from the gofrontend repository.\nIndex: gcc/go/gofrontend/expressions.cc\n===================================================================\n--- gcc/go/gofrontend/expressions.cc\t(revision 252748)\n+++ gcc/go/gofrontend/expressions.cc\t(working copy)\n@@ -14463,15 +14463,14 @@ Receive_expression::do_get_backend(Trans\n       go_assert(this->channel_->type()->is_error());\n       return context->backend()->error_expression();\n     }\n-  Expression* td = Expression::make_type_descriptor(channel_type, loc);\n \n   Expression* recv_ref =\n     Expression::make_temporary_reference(this->temp_receiver_, loc);\n   Expression* recv_addr =\n     Expression::make_temporary_reference(this->temp_receiver_, loc);\n   recv_addr = Expression::make_unary(OPERATOR_AND, recv_addr, loc);\n-  Expression* recv = Runtime::make_call(Runtime::CHANRECV1, loc, 3,\n-\t\t\t\t\ttd, this->channel_, recv_addr);\n+  Expression* recv = Runtime::make_call(Runtime::CHANRECV1, loc, 2,\n+\t\t\t\t\tthis->channel_, recv_addr);\n   return Expression::make_compound(recv, recv_ref, loc)->get_backend(context);\n }\n \nIndex: gcc/go/gofrontend/runtime.def\n===================================================================\n--- gcc/go/gofrontend/runtime.def\t(revision 251948)\n+++ gcc/go/gofrontend/runtime.def\t(working copy)\n@@ -137,39 +137,31 @@ DEF_GO_RUNTIME(MAPITERNEXT, \"runtime.map\n DEF_GO_RUNTIME(MAKECHAN, \"runtime.makechan\", P2(TYPE, INT64), R1(CHAN))\n \n // Send a value on a channel.\n-DEF_GO_RUNTIME(CHANSEND, \"runtime.chansend1\", P3(TYPE, CHAN, POINTER), R0())\n+DEF_GO_RUNTIME(CHANSEND, \"runtime.chansend1\", P2(CHAN, POINTER), R0())\n \n // Receive a value from a channel.\n-DEF_GO_RUNTIME(CHANRECV1, \"runtime.chanrecv1\", P3(TYPE, CHAN, POINTER), R0())\n+DEF_GO_RUNTIME(CHANRECV1, \"runtime.chanrecv1\", P2(CHAN, POINTER), R0())\n \n // Receive a value from a channel returning whether it is closed.\n-DEF_GO_RUNTIME(CHANRECV2, \"runtime.chanrecv2\", P3(TYPE, CHAN, POINTER),\n-\t       R1(BOOL))\n+DEF_GO_RUNTIME(CHANRECV2, \"runtime.chanrecv2\", P2(CHAN, POINTER), R1(BOOL))\n \n \n // Start building a select statement.\n DEF_GO_RUNTIME(NEWSELECT, \"runtime.newselect\", P3(POINTER, INT64, INT32), R0())\n \n // Add a default clause to a select statement.\n-DEF_GO_RUNTIME(SELECTDEFAULT, \"runtime.selectdefault\",\n-\t       P2(POINTER, INT32), R0())\n+DEF_GO_RUNTIME(SELECTDEFAULT, \"runtime.selectdefault\", P1(POINTER), R0())\n \n // Add a send clause to a select statement.\n-DEF_GO_RUNTIME(SELECTSEND, \"runtime.selectsend\",\n-\t       P4(POINTER, CHAN, POINTER, INT32), R0())\n+DEF_GO_RUNTIME(SELECTSEND, \"runtime.selectsend\", P3(POINTER, CHAN, POINTER),\n+\t       R0())\n \n-// Add a receive clause to a select statement, for a clause which does\n-// not check whether the channel is closed.\n+// Add a receive clause to a select statement.\n DEF_GO_RUNTIME(SELECTRECV, \"runtime.selectrecv\",\n-\t       P4(POINTER, CHAN, POINTER, INT32), R0())\n-\n-// Add a receive clause to a select statement, for a clause which does\n-// check whether the channel is closed.\n-DEF_GO_RUNTIME(SELECTRECV2, \"runtime.selectrecv2\",\n-\t       P5(POINTER, CHAN, POINTER, BOOLPTR, INT32), R0())\n+\t       P4(POINTER, CHAN, POINTER, BOOLPTR), R0())\n \n // Run a select, returning the index of the selected clause.\n-DEF_GO_RUNTIME(SELECTGO, \"runtime.selectgo\", P1(POINTER), R1(INT32))\n+DEF_GO_RUNTIME(SELECTGO, \"runtime.selectgo\", P1(POINTER), R1(INT))\n \n \n // Panic.\nIndex: gcc/go/gofrontend/statements.cc\n===================================================================\n--- gcc/go/gofrontend/statements.cc\t(revision 251948)\n+++ gcc/go/gofrontend/statements.cc\t(working copy)\n@@ -1517,14 +1517,12 @@ Tuple_receive_assignment_statement::do_l\n \t\t\t      NULL, loc);\n   b->add_statement(closed_temp);\n \n-  // closed_temp = chanrecv2(type, channel, &val_temp)\n-  Expression* td = Expression::make_type_descriptor(this->channel_->type(),\n-\t\t\t\t\t\t    loc);\n+  // closed_temp = chanrecv2(channel, &val_temp)\n   Temporary_reference_expression* ref =\n     Expression::make_temporary_reference(val_temp, loc);\n   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);\n   Expression* call = Runtime::make_call(Runtime::CHANRECV2,\n-\t\t\t\t\tloc, 3, td, this->channel_, p2);\n+\t\t\t\t\tloc, 2, this->channel_, p2);\n   ref = Expression::make_temporary_reference(closed_temp, loc);\n   ref->set_is_lvalue();\n   Statement* s = Statement::make_assignment(ref, call, loc);\n@@ -4516,9 +4514,6 @@ Send_statement::do_get_backend(Translate\n       && val->temporary_reference_expression() == NULL)\n     can_take_address = false;\n \n-  Expression* td = Expression::make_type_descriptor(this->channel_->type(),\n-\t\t\t\t\t\t    loc);\n-\n   Bstatement* btemp = NULL;\n   if (can_take_address)\n     {\n@@ -4539,7 +4534,7 @@ Send_statement::do_get_backend(Translate\n       btemp = temp->get_backend(context);\n     }\n \n-  Expression* call = Runtime::make_call(Runtime::CHANSEND, loc, 3, td,\n+  Expression* call = Runtime::make_call(Runtime::CHANSEND, loc, 2,\n \t\t\t\t\tthis->channel_, val);\n \n   context->gogo()->lower_expression(context->function(), NULL, &call);\n@@ -4621,13 +4616,10 @@ Select_clauses::Select_clause::lower(Gog\n   Expression* selref = Expression::make_temporary_reference(sel, loc);\n   selref = Expression::make_unary(OPERATOR_AND, selref, loc);\n \n-  Expression* index_expr = Expression::make_integer_ul(this->index_, NULL,\n-\t\t\t\t\t\t       loc);\n-\n   if (this->is_default_)\n     {\n       go_assert(this->channel_ == NULL && this->val_ == NULL);\n-      this->lower_default(b, selref, index_expr);\n+      this->lower_default(b, selref);\n       this->is_lowered_ = true;\n       return;\n     }\n@@ -4641,9 +4633,9 @@ Select_clauses::Select_clause::lower(Gog\n \t\t\t\t\t\t\t     loc);\n \n   if (this->is_send_)\n-    this->lower_send(b, selref, chanref, index_expr);\n+    this->lower_send(b, selref, chanref);\n   else\n-    this->lower_recv(gogo, function, b, selref, chanref, index_expr);\n+    this->lower_recv(gogo, function, b, selref, chanref);\n \n   // Now all references should be handled through the statements, not\n   // through here.\n@@ -4654,12 +4646,11 @@ Select_clauses::Select_clause::lower(Gog\n // Lower a default clause in a select statement.\n \n void\n-Select_clauses::Select_clause::lower_default(Block* b, Expression* selref,\n-\t\t\t\t\t     Expression* index_expr)\n+Select_clauses::Select_clause::lower_default(Block* b, Expression* selref)\n {\n   Location loc = this->location_;\n-  Expression* call = Runtime::make_call(Runtime::SELECTDEFAULT, loc, 2, selref,\n-\t\t\t\t\tindex_expr);\n+  Expression* call = Runtime::make_call(Runtime::SELECTDEFAULT, loc, 1,\n+\t\t\t\t\tselref);\n   b->add_statement(Statement::make_statement(call, true));\n }\n \n@@ -4667,8 +4658,7 @@ Select_clauses::Select_clause::lower_def\n \n void\n Select_clauses::Select_clause::lower_send(Block* b, Expression* selref,\n-\t\t\t\t\t  Expression* chanref,\n-\t\t\t\t\t  Expression* index_expr)\n+\t\t\t\t\t  Expression* chanref)\n {\n   Location loc = this->location_;\n \n@@ -4687,8 +4677,8 @@ Select_clauses::Select_clause::lower_sen\n   Expression* valref = Expression::make_temporary_reference(val, loc);\n   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);\n \n-  Expression* call = Runtime::make_call(Runtime::SELECTSEND, loc, 4, selref,\n-\t\t\t\t\tchanref, valaddr, index_expr);\n+  Expression* call = Runtime::make_call(Runtime::SELECTSEND, loc, 3, selref,\n+\t\t\t\t\tchanref, valaddr);\n   b->add_statement(Statement::make_statement(call, true));\n }\n \n@@ -4697,8 +4687,7 @@ Select_clauses::Select_clause::lower_sen\n void\n Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,\n \t\t\t\t\t  Block* b, Expression* selref,\n-\t\t\t\t\t  Expression* chanref,\n-\t\t\t\t\t  Expression* index_expr)\n+\t\t\t\t\t  Expression* chanref)\n {\n   Location loc = this->location_;\n \n@@ -4715,10 +4704,9 @@ Select_clauses::Select_clause::lower_rec\n \n   Temporary_statement* closed_temp = NULL;\n \n-  Expression* call;\n+  Expression* caddr;\n   if (this->closed_ == NULL && this->closedvar_ == NULL)\n-    call = Runtime::make_call(Runtime::SELECTRECV, loc, 4, selref, chanref,\n-\t\t\t      valaddr, index_expr);\n+    caddr = Expression::make_nil(loc);\n   else\n     {\n       closed_temp = Statement::make_temporary(Type::lookup_bool_type(), NULL,\n@@ -4726,11 +4714,12 @@ Select_clauses::Select_clause::lower_rec\n       b->add_statement(closed_temp);\n       Expression* cref = Expression::make_temporary_reference(closed_temp,\n \t\t\t\t\t\t\t      loc);\n-      Expression* caddr = Expression::make_unary(OPERATOR_AND, cref, loc);\n-      call = Runtime::make_call(Runtime::SELECTRECV2, loc, 5, selref, chanref,\n-\t\t\t\tvaladdr, caddr, index_expr);\n+      caddr = Expression::make_unary(OPERATOR_AND, cref, loc);\n     }\n \n+  Expression* call = Runtime::make_call(Runtime::SELECTRECV, loc, 4, selref,\n+\t\t\t\t\tchanref, valaddr, caddr);\n+\n   b->add_statement(Statement::make_statement(call, true));\n \n   // If the block of statements is executed, arrange for the received\n@@ -4958,15 +4947,14 @@ Select_clauses::get_backend(Translate_co\n   std::vector<std::vector<Bexpression*> > cases(count);\n   std::vector<Bstatement*> clauses(count);\n \n-  Type* int32_type = Type::lookup_integer_type(\"int32\");\n+  Type* int_type = Type::lookup_integer_type(\"int\");\n \n   int i = 0;\n   for (Clauses::iterator p = this->clauses_.begin();\n        p != this->clauses_.end();\n        ++p, ++i)\n     {\n-      int index = p->index();\n-      Expression* index_expr = Expression::make_integer_ul(index, int32_type,\n+      Expression* index_expr = Expression::make_integer_ul(i, int_type,\n \t\t\t\t\t\t\t   location);\n       cases[i].push_back(index_expr->get_backend(context));\n \nIndex: gcc/go/gofrontend/statements.h\n===================================================================\n--- gcc/go/gofrontend/statements.h\t(revision 251948)\n+++ gcc/go/gofrontend/statements.h\t(working copy)\n@@ -899,10 +899,9 @@ class Select_clauses\n       Named_object* var, Named_object* closedvar, bool is_default,\n       Block* statements, Location location)\n   {\n-    int index = static_cast<int>(this->clauses_.size());\n-    this->clauses_.push_back(Select_clause(index, is_send, channel, val,\n-\t\t\t\t\t   closed, var, closedvar, is_default,\n-\t\t\t\t\t   statements, location));\n+    this->clauses_.push_back(Select_clause(is_send, channel, val, closed, var,\n+\t\t\t\t\t   closedvar, is_default, statements,\n+\t\t\t\t\t   location));\n   }\n \n   size_t\n@@ -950,21 +949,15 @@ class Select_clauses\n \tis_default_(false)\n     { }\n \n-    Select_clause(int index, bool is_send, Expression* channel,\n-\t\t  Expression* val, Expression* closed, Named_object* var,\n+    Select_clause(bool is_send, Expression* channel, Expression* val,\n+\t\t  Expression* closed, Named_object* var,\n \t\t  Named_object* closedvar, bool is_default, Block* statements,\n \t\t  Location location)\n-      : index_(index), channel_(channel), val_(val), closed_(closed),\n-\tvar_(var), closedvar_(closedvar), statements_(statements),\n-\tlocation_(location), is_send_(is_send), is_default_(is_default),\n-\tis_lowered_(false)\n+      : channel_(channel), val_(val), closed_(closed), var_(var),\n+\tclosedvar_(closedvar), statements_(statements), location_(location),\n+\tis_send_(is_send), is_default_(is_default), is_lowered_(false)\n     { go_assert(is_default ? channel == NULL : channel != NULL); }\n \n-    // Return the index of this clause.\n-    int\n-    index() const\n-    { return this->index_; }\n-\n     // Traverse the select clause.\n     int\n     traverse(Traverse*);\n@@ -1025,17 +1018,14 @@ class Select_clauses\n \n    private:\n     void\n-    lower_default(Block*, Expression*, Expression*);\n+    lower_default(Block*, Expression*);\n \n     void\n-    lower_send(Block*, Expression*, Expression*, Expression*);\n+    lower_send(Block*, Expression*, Expression*);\n \n     void\n-    lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*,\n-\t       Expression*);\n+    lower_recv(Gogo*, Named_object*, Block*, Expression*, Expression*);\n \n-    // The index of this case in the generated switch statement.\n-    int index_;\n     // The channel.\n     Expression* channel_;\n     // The value to send or the lvalue to receive into.\nIndex: libgo/go/reflect/value.go\n===================================================================\n--- libgo/go/reflect/value.go\t(revision 252746)\n+++ libgo/go/reflect/value.go\t(working copy)\n@@ -1160,7 +1160,7 @@ func (v Value) recv(nb bool) (val Value,\n \t} else {\n \t\tp = unsafe.Pointer(&val.ptr)\n \t}\n-\tselected, ok := chanrecv(v.typ, v.pointer(), nb, p)\n+\tselected, ok := chanrecv(v.pointer(), nb, p)\n \tif !selected {\n \t\tval = Value{}\n \t}\n@@ -1191,7 +1191,7 @@ func (v Value) send(x Value, nb bool) (s\n \t} else {\n \t\tp = unsafe.Pointer(&x.ptr)\n \t}\n-\treturn chansend(v.typ, v.pointer(), p, nb)\n+\treturn chansend(v.pointer(), p, nb)\n }\n \n // Set assigns x to the value v.\n@@ -2327,10 +2327,10 @@ func chanlen(ch unsafe.Pointer) int\n // (due to the escapes() call in ValueOf).\n \n //go:noescape\n-func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)\n+func chanrecv(ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)\n \n //go:noescape\n-func chansend(t *rtype, ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool\n+func chansend(ch unsafe.Pointer, val unsafe.Pointer, nb bool) bool\n \n func makechan(typ *rtype, size uint64) (ch unsafe.Pointer)\n func makemap(t *rtype) (m unsafe.Pointer)\nIndex: libgo/go/runtime/chan.go\n===================================================================\n--- libgo/go/runtime/chan.go\t(revision 251948)\n+++ libgo/go/runtime/chan.go\t(working copy)\n@@ -118,8 +118,8 @@ func chanbuf(c *hchan, i uint) unsafe.Po\n \n // entry point for c <- x from compiled code\n //go:nosplit\n-func chansend1(t *chantype, c *hchan, elem unsafe.Pointer) {\n-\tchansend(t, c, elem, true, getcallerpc(unsafe.Pointer(&t)))\n+func chansend1(c *hchan, elem unsafe.Pointer) {\n+\tchansend(c, elem, true, getcallerpc(unsafe.Pointer(&c)))\n }\n \n /*\n@@ -134,14 +134,7 @@ func chansend1(t *chantype, c *hchan, el\n  * been closed.  it is easiest to loop and re-run\n  * the operation; we'll see that it's now closed.\n  */\n-func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {\n-\tif raceenabled {\n-\t\traceReadObjectPC(t.elem, ep, callerpc, funcPC(chansend))\n-\t}\n-\tif msanenabled {\n-\t\tmsanread(ep, t.elem.size)\n-\t}\n-\n+func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {\n \tif c == nil {\n \t\tif !block {\n \t\t\treturn false\n@@ -400,13 +393,13 @@ func closechan(c *hchan) {\n \n // entry points for <- c from compiled code\n //go:nosplit\n-func chanrecv1(t *chantype, c *hchan, elem unsafe.Pointer) {\n-\tchanrecv(t, c, elem, true)\n+func chanrecv1(c *hchan, elem unsafe.Pointer) {\n+\tchanrecv(c, elem, true)\n }\n \n //go:nosplit\n-func chanrecv2(t *chantype, c *hchan, elem unsafe.Pointer) (received bool) {\n-\t_, received = chanrecv(t, c, elem, true)\n+func chanrecv2(c *hchan, elem unsafe.Pointer) (received bool) {\n+\t_, received = chanrecv(c, elem, true)\n \treturn\n }\n \n@@ -416,7 +409,7 @@ func chanrecv2(t *chantype, c *hchan, el\n // Otherwise, if c is closed, zeros *ep and returns (true, false).\n // Otherwise, fills in *ep with an element and returns (true, true).\n // A non-nil ep must point to the heap or the caller's stack.\n-func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {\n+func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {\n \t// raceenabled: don't need to check ep, as it is always on the stack\n \t// or is new memory allocated by reflect.\n \n@@ -609,8 +602,8 @@ func recv(c *hchan, sg *sudog, ep unsafe\n //\t\t... bar\n //\t}\n //\n-func selectnbsend(t *chantype, c *hchan, elem unsafe.Pointer) (selected bool) {\n-\treturn chansend(t, c, elem, false, getcallerpc(unsafe.Pointer(&t)))\n+func selectnbsend(c *hchan, elem unsafe.Pointer) (selected bool) {\n+\treturn chansend(c, elem, false, getcallerpc(unsafe.Pointer(&c)))\n }\n \n // compiler implements\n@@ -630,8 +623,8 @@ func selectnbsend(t *chantype, c *hchan,\n //\t\t... bar\n //\t}\n //\n-func selectnbrecv(t *chantype, elem unsafe.Pointer, c *hchan) (selected bool) {\n-\tselected, _ = chanrecv(t, c, elem, false)\n+func selectnbrecv(elem unsafe.Pointer, c *hchan) (selected bool) {\n+\tselected, _ = chanrecv(c, elem, false)\n \treturn\n }\n \n@@ -652,20 +645,20 @@ func selectnbrecv(t *chantype, elem unsa\n //\t\t... bar\n //\t}\n //\n-func selectnbrecv2(t *chantype, elem unsafe.Pointer, received *bool, c *hchan) (selected bool) {\n+func selectnbrecv2(elem unsafe.Pointer, received *bool, c *hchan) (selected bool) {\n \t// TODO(khr): just return 2 values from this function, now that it is in Go.\n-\tselected, *received = chanrecv(t, c, elem, false)\n+\tselected, *received = chanrecv(c, elem, false)\n \treturn\n }\n \n //go:linkname reflect_chansend reflect.chansend\n-func reflect_chansend(t *chantype, c *hchan, elem unsafe.Pointer, nb bool) (selected bool) {\n-\treturn chansend(t, c, elem, !nb, getcallerpc(unsafe.Pointer(&t)))\n+func reflect_chansend(c *hchan, elem unsafe.Pointer, nb bool) (selected bool) {\n+\treturn chansend(c, elem, !nb, getcallerpc(unsafe.Pointer(&c)))\n }\n \n //go:linkname reflect_chanrecv reflect.chanrecv\n-func reflect_chanrecv(t *chantype, c *hchan, nb bool, elem unsafe.Pointer) (selected bool, received bool) {\n-\treturn chanrecv(t, c, elem, !nb)\n+func reflect_chanrecv(c *hchan, nb bool, elem unsafe.Pointer) (selected bool, received bool) {\n+\treturn chanrecv(c, elem, !nb)\n }\n \n //go:linkname reflect_chanlen reflect.chanlen\nIndex: libgo/go/runtime/select.go\n===================================================================\n--- libgo/go/runtime/select.go\t(revision 251948)\n+++ libgo/go/runtime/select.go\t(working copy)\n@@ -18,14 +18,14 @@ import (\n //go:linkname selectdefault runtime.selectdefault\n //go:linkname selectsend runtime.selectsend\n //go:linkname selectrecv runtime.selectrecv\n-//go:linkname selectrecv2 runtime.selectrecv2\n //go:linkname selectgo runtime.selectgo\n \n-const (\n-\tdebugSelect = false\n+const debugSelect = false\n \n+const (\n \t// scase.kind\n-\tcaseRecv = iota\n+\tcaseNil = iota\n+\tcaseRecv\n \tcaseSend\n \tcaseDefault\n )\n@@ -47,10 +47,9 @@ type hselect struct {\n type scase struct {\n \telem        unsafe.Pointer // data element\n \tc           *hchan         // chan\n-\tpc          uintptr        // return pc\n+\tpc          uintptr        // return pc (for race detector / msan)\n \tkind        uint16\n-\tindex       uint16 // case index\n-\treceivedp   *bool  // pointer to received bool (recv2)\n+\treceivedp   *bool // pointer to received bool, if any\n \treleasetime int64\n }\n \n@@ -88,88 +87,64 @@ func newselect(sel *hselect, selsize int\n \t}\n }\n \n-func selectsend(sel *hselect, c *hchan, elem unsafe.Pointer, index int32) {\n-\t// nil cases do not compete\n-\tif c != nil {\n-\t\tselectsendImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, index)\n-\t}\n-\treturn\n-}\n-\n-// cut in half to give stack a chance to split\n-func selectsendImpl(sel *hselect, c *hchan, pc uintptr, elem unsafe.Pointer, index int32) {\n+func selectsend(sel *hselect, c *hchan, elem unsafe.Pointer) {\n+\tpc := getcallerpc(unsafe.Pointer(&sel))\n \ti := sel.ncase\n \tif i >= sel.tcase {\n \t\tthrow(\"selectsend: too many cases\")\n \t}\n \tsel.ncase = i + 1\n+\tif c == nil {\n+\t\treturn\n+\t}\n \tcas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))\n \n \tcas.pc = pc\n \tcas.c = c\n-\tcas.index = uint16(index)\n \tcas.kind = caseSend\n \tcas.elem = elem\n \n \tif debugSelect {\n-\t\tprint(\"selectsend s=\", sel, \" pc=\", hex(cas.pc), \" chan=\", cas.c, \" index=\", cas.index, \"\\n\")\n+\t\tprint(\"selectsend s=\", sel, \" pc=\", hex(cas.pc), \" chan=\", cas.c, \"\\n\")\n \t}\n }\n \n-func selectrecv(sel *hselect, c *hchan, elem unsafe.Pointer, index int32) {\n-\t// nil cases do not compete\n-\tif c != nil {\n-\t\tselectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, nil, index)\n-\t}\n-\treturn\n-}\n-\n-func selectrecv2(sel *hselect, c *hchan, elem unsafe.Pointer, received *bool, index int32) {\n-\t// nil cases do not compete\n-\tif c != nil {\n-\t\tselectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, received, index)\n-\t}\n-\treturn\n-}\n-\n-func selectrecvImpl(sel *hselect, c *hchan, pc uintptr, elem unsafe.Pointer, received *bool, index int32) {\n+func selectrecv(sel *hselect, c *hchan, elem unsafe.Pointer, received *bool) {\n+\tpc := getcallerpc(unsafe.Pointer(&sel))\n \ti := sel.ncase\n \tif i >= sel.tcase {\n \t\tthrow(\"selectrecv: too many cases\")\n \t}\n \tsel.ncase = i + 1\n+\tif c == nil {\n+\t\treturn\n+\t}\n \tcas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))\n \tcas.pc = pc\n \tcas.c = c\n-\tcas.index = uint16(index)\n \tcas.kind = caseRecv\n \tcas.elem = elem\n \tcas.receivedp = received\n \n \tif debugSelect {\n-\t\tprint(\"selectrecv s=\", sel, \" pc=\", hex(cas.pc), \" chan=\", cas.c, \" index=\", cas.index, \"\\n\")\n+\t\tprint(\"selectrecv s=\", sel, \" pc=\", hex(cas.pc), \" chan=\", cas.c, \"\\n\")\n \t}\n }\n \n-func selectdefault(sel *hselect, index int32) {\n-\tselectdefaultImpl(sel, getcallerpc(unsafe.Pointer(&sel)), index)\n-\treturn\n-}\n-\n-func selectdefaultImpl(sel *hselect, callerpc uintptr, index int32) {\n+func selectdefault(sel *hselect) {\n+\tpc := getcallerpc(unsafe.Pointer(&sel))\n \ti := sel.ncase\n \tif i >= sel.tcase {\n \t\tthrow(\"selectdefault: too many cases\")\n \t}\n \tsel.ncase = i + 1\n \tcas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))\n-\tcas.pc = callerpc\n+\tcas.pc = pc\n \tcas.c = nil\n-\tcas.index = uint16(index)\n \tcas.kind = caseDefault\n \n \tif debugSelect {\n-\t\tprint(\"selectdefault s=\", sel, \" pc=\", hex(cas.pc), \" index=\", cas.index, \"\\n\")\n+\t\tprint(\"selectdefault s=\", sel, \" pc=\", hex(cas.pc), \"\\n\")\n \t}\n }\n \n@@ -193,14 +168,11 @@ func selunlock(scases []scase, lockorder\n \t// the G that calls select runnable again and schedules it for execution.\n \t// When the G runs on another M, it locks all the locks and frees sel.\n \t// Now if the first M touches sel, it will access freed memory.\n-\tn := len(scases)\n-\tr := 0\n-\t// skip the default case\n-\tif n > 0 && scases[lockorder[0]].c == nil {\n-\t\tr = 1\n-\t}\n-\tfor i := n - 1; i >= r; i-- {\n+\tfor i := len(scases) - 1; i >= 0; i-- {\n \t\tc := scases[lockorder[i]].c\n+\t\tif c == nil {\n+\t\t\tbreak\n+\t\t}\n \t\tif i > 0 && c == scases[lockorder[i-1]].c {\n \t\t\tcontinue // will unlock it on the next iteration\n \t\t}\n@@ -241,20 +213,15 @@ func block() {\n // *sel is on the current goroutine's stack (regardless of any\n // escaping in selectgo).\n //\n-// selectgo does not return. Instead, it overwrites its return PC and\n-// returns directly to the triggered select case. Because of this, it\n-// cannot appear at the top of a split stack.\n-func selectgo(sel *hselect) int32 {\n-\t_, index := selectgoImpl(sel)\n-\treturn int32(index)\n-}\n-\n-// selectgoImpl returns scase.pc and scase.so for the select\n-// case which fired.\n-func selectgoImpl(sel *hselect) (uintptr, uint16) {\n+// selectgo returns the index of the chosen scase, which matches the\n+// ordinal position of its respective select{recv,send,default} call.\n+func selectgo(sel *hselect) int {\n \tif debugSelect {\n \t\tprint(\"select: sel=\", sel, \"\\n\")\n \t}\n+\tif sel.ncase != sel.tcase {\n+\t\tthrow(\"selectgo: case count mismatch\")\n+\t}\n \n \tscaseslice := slice{unsafe.Pointer(&sel.scase), int(sel.ncase), int(sel.ncase)}\n \tscases := *(*[]scase)(unsafe.Pointer(&scaseslice))\n@@ -347,13 +314,19 @@ func selectgoImpl(sel *hselect) (uintptr\n \n loop:\n \t// pass 1 - look for something already waiting\n+\tvar dfli int\n \tvar dfl *scase\n+\tvar casi int\n \tvar cas *scase\n \tfor i := 0; i < int(sel.ncase); i++ {\n-\t\tcas = &scases[pollorder[i]]\n+\t\tcasi = int(pollorder[i])\n+\t\tcas = &scases[casi]\n \t\tc = cas.c\n \n \t\tswitch cas.kind {\n+\t\tcase caseNil:\n+\t\t\tcontinue\n+\n \t\tcase caseRecv:\n \t\t\tsg = c.sendq.dequeue()\n \t\t\tif sg != nil {\n@@ -382,12 +355,14 @@ loop:\n \t\t\t}\n \n \t\tcase caseDefault:\n+\t\t\tdfli = casi\n \t\t\tdfl = cas\n \t\t}\n \t}\n \n \tif dfl != nil {\n \t\tselunlock(scases, lockorder)\n+\t\tcasi = dfli\n \t\tcas = dfl\n \t\tgoto retc\n \t}\n@@ -400,7 +375,11 @@ loop:\n \t}\n \tnextp = &gp.waiting\n \tfor _, casei := range lockorder {\n-\t\tcas = &scases[casei]\n+\t\tcasi = int(casei)\n+\t\tcas = &scases[casi]\n+\t\tif cas.kind == caseNil {\n+\t\t\tcontinue\n+\t\t}\n \t\tc = cas.c\n \t\tsg := acquireSudog()\n \t\tsg.g = gp\n@@ -494,6 +473,7 @@ loop:\n \t// otherwise they stack up on quiet channels\n \t// record the successful case, if any.\n \t// We singly-linked up the SudoGs in lock order.\n+\tcasi = -1\n \tcas = nil\n \tsglist = gp.waiting\n \t// Clear all elem before unlinking from gp.waiting.\n@@ -506,11 +486,15 @@ loop:\n \n \tfor _, casei := range lockorder {\n \t\tk = &scases[casei]\n+\t\tif k.kind == caseNil {\n+\t\t\tcontinue\n+\t\t}\n \t\tif sglist.releasetime > 0 {\n \t\t\tk.releasetime = sglist.releasetime\n \t\t}\n \t\tif sg == sglist {\n \t\t\t// sg has already been dequeued by the G that woke us up.\n+\t\t\tcasi = int(casei)\n \t\t\tcas = k\n \t\t} else {\n \t\t\tc = k.c\n@@ -659,7 +643,7 @@ retc:\n \tif cas.releasetime > 0 {\n \t\tblockevent(cas.releasetime-t0, 2)\n \t}\n-\treturn cas.pc, cas.index\n+\treturn casi\n \n sclose:\n \t// send on closed channel\n@@ -703,22 +687,15 @@ func reflect_rselect(cases []runtimeSele\n \t\trc := &cases[i]\n \t\tswitch rc.dir {\n \t\tcase selectDefault:\n-\t\t\tselectdefaultImpl(sel, uintptr(i), 0)\n+\t\t\tselectdefault(sel)\n \t\tcase selectSend:\n-\t\t\tif rc.ch == nil {\n-\t\t\t\tbreak\n-\t\t\t}\n-\t\t\tselectsendImpl(sel, rc.ch, uintptr(i), rc.val, 0)\n+\t\t\tselectsend(sel, rc.ch, rc.val)\n \t\tcase selectRecv:\n-\t\t\tif rc.ch == nil {\n-\t\t\t\tbreak\n-\t\t\t}\n-\t\t\tselectrecvImpl(sel, rc.ch, uintptr(i), rc.val, r, 0)\n+\t\t\tselectrecv(sel, rc.ch, rc.val, r)\n \t\t}\n \t}\n \n-\tpc, _ := selectgoImpl(sel)\n-\tchosen = int(pc)\n+\tchosen = selectgo(sel)\n \trecvOK = *r\n \treturn\n }\n","prefixes":[]}