diff options
Diffstat (limited to 'src/cmd/gc/gen.c')
-rw-r--r-- | src/cmd/gc/gen.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 955ec2c5b..ada16eacc 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -489,11 +489,12 @@ gen(Node *n) break; case ORETURN: + case ORETJMP: cgen_ret(n); break; - case OCHECKNOTNIL: - checkref(n->left, 1); + case OCHECKNIL: + cgen_checknil(n->left); } ret: @@ -628,6 +629,10 @@ cgen_discard(Node *nr) case OPLUS: cgen_discard(nr->left); break; + + case OIND: + cgen_checknil(nr->left); + break; // special enough to just evaluate default: @@ -776,6 +781,8 @@ cgen_eface(Node *n, Node *res) * n->left is s * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)]) * caller (cgen) guarantees res is an addable ONAME. + * + * called for OSLICE, OSLICE3, OSLICEARR, OSLICE3ARR, OSLICESTR. */ void cgen_slice(Node *n, Node *res) @@ -807,21 +814,26 @@ cgen_slice(Node *n, Node *res) dst.xoffset += Array_array; dst.type = types[TUINTPTR]; - if(n->op == OSLICEARR) { - if(!isptr[n->left->type->etype]) - fatal("slicearr is supposed to work on pointer: %+N\n", n); - checkref(n->left, 0); - } - if(isnil(n->left)) { tempname(&src, n->left->type); cgen(n->left, &src); } else src = *n->left; - src.xoffset += Array_array; + if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR) + src.xoffset += Array_array; src.type = types[TUINTPTR]; - if(offs == N) { + if(n->op == OSLICEARR || n->op == OSLICE3ARR) { + if(!isptr[n->left->type->etype]) + fatal("slicearr is supposed to work on pointer: %+N\n", n); + cgen(&src, &dst); + cgen_checknil(&dst); + if(offs != N) { + add = nod(OADD, &dst, offs); + typecheck(&add, Erv); + cgen(add, &dst); + } + } else if(offs == N) { cgen(&src, &dst); } else { add = nod(OADD, &src, offs); |