diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/cmd/gc/select.c | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/cmd/gc/select.c')
-rw-r--r-- | src/cmd/gc/select.c | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c index 58a120674..965ad277f 100644 --- a/src/cmd/gc/select.c +++ b/src/cmd/gc/select.c @@ -10,6 +10,8 @@ #include <libc.h> #include "go.h" +static Type* selecttype(int32 size); + void typecheckselect(Node *sel) { @@ -95,7 +97,7 @@ void walkselect(Node *sel) { int lno, i; - Node *n, *r, *a, *var, *cas, *dflt, *ch; + Node *n, *r, *a, *var, *selv, *cas, *dflt, *ch; NodeList *l, *init; if(sel->list == nil && sel->xoffset != 0) @@ -257,8 +259,12 @@ walkselect(Node *sel) // generate sel-struct setlineno(sel); - var = temp(ptrto(types[TUINT8])); - r = nod(OAS, var, mkcall("newselect", var->type, nil, nodintconst(sel->xoffset))); + selv = temp(selecttype(sel->xoffset)); + r = nod(OAS, selv, N); + typecheck(&r, Etop); + init = list(init, r); + var = conv(conv(nod(OADDR, selv, N), types[TUNSAFEPTR]), ptrto(types[TUINT8])); + r = mkcall("newselect", T, nil, var, nodintconst(selv->type->width), nodintconst(sel->xoffset)); typecheck(&r, Etop); init = list(init, r); @@ -301,6 +307,8 @@ walkselect(Node *sel) break; } } + // selv is no longer alive after use. + r->nbody = list(r->nbody, nod(OVARKILL, selv, N)); r->nbody = concat(r->nbody, cas->nbody); r->nbody = list(r->nbody, nod(OBREAK, N, N)); init = list(init, r); @@ -316,3 +324,54 @@ out: walkstmtlist(sel->nbody); lineno = lno; } + +// Keep in sync with src/runtime/chan.h. +static Type* +selecttype(int32 size) +{ + Node *sel, *sudog, *scase, *arr; + + // TODO(dvyukov): it's possible to generate SudoG and Scase only once + // and then cache; and also cache Select per size. + sudog = nod(OTSTRUCT, N, N); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("g")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("selectdone")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("link")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("prev")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8])))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64]))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("nrelease")), typenod(types[TINT32]))); + sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("waitlink")), typenod(ptrto(types[TUINT8])))); + typecheck(&sudog, Etype); + sudog->type->noalg = 1; + sudog->type->local = 1; + + scase = nod(OTSTRUCT, N, N); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("chan")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("pc")), typenod(types[TUINTPTR]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("kind")), typenod(types[TUINT16]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("so")), typenod(types[TUINT16]))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("receivedp")), typenod(ptrto(types[TUINT8])))); + scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64]))); + typecheck(&scase, Etype); + scase->type->noalg = 1; + scase->type->local = 1; + + sel = nod(OTSTRUCT, N, N); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("tcase")), typenod(types[TUINT16]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("ncase")), typenod(types[TUINT16]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorder")), typenod(ptrto(types[TUINT8])))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorder")), typenod(ptrto(types[TUINT8])))); + arr = nod(OTARRAY, nodintconst(size), scase); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("scase")), arr)); + arr = nod(OTARRAY, nodintconst(size), typenod(ptrto(types[TUINT8]))); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorderarr")), arr)); + arr = nod(OTARRAY, nodintconst(size), typenod(types[TUINT16])); + sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorderarr")), arr)); + typecheck(&sel, Etype); + sel->type->noalg = 1; + sel->type->local = 1; + + return sel->type; +} |