aboutsummaryrefslogtreecommitdiff
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.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 5012e4a52d..9806600277 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -734,6 +734,66 @@ ret:
;
}
+
+/*
+ * generate:
+ * res = s[lo, hi];
+ * n->left is s
+ * n->list is (cap(s)-lo(TUINT32), hi-lo(TUINT32)[, lo*width(TUINTPTR)])
+ * caller (cgen) guarantees res is an addable ONAME.
+ *
+ */
+void
+cgen_slice(Node *n, Node *res)
+{
+ Node src, dst, *cap, *len, *offs, *add;
+
+// print("cgen_slice: %N = %+N\n", res, n);
+
+ cap = n->list->n;
+ len = n->list->next->n;
+ offs = N;
+ if(n->list->next->next)
+ offs = n->list->next->next->n;
+
+ // dst.len = hi [ - lo ]
+ dst = *res;
+ dst.xoffset += Array_nel;
+ dst.type = types[TUINT32];
+ cgen(len, &dst);
+
+ if(n->op != OSLICESTR) {
+ // dst.cap = cap [ - lo ]
+ dst = *res;
+ dst.xoffset += Array_cap;
+ dst.type = types[TUINT32];
+ cgen(cap, &dst);
+ }
+
+ // dst.array = src.array [ + lo *width ]
+ dst = *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);
+ }
+
+ src = *n->left;
+ src.xoffset += Array_array;
+ src.type = types[TUINTPTR];
+
+ if(offs == N) {
+ cgen(&src, &dst);
+ } else {
+ add = nod(OADD, &src, offs);
+ typecheck(&add, Erv);
+ cgen(add, &dst);
+ }
+}
+
/*
* gather series of offsets
* >=0 is direct addressed field