summaryrefslogtreecommitdiff
path: root/src/cmd/gc/gen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/gen.c')
-rw-r--r--src/cmd/gc/gen.c32
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);