summaryrefslogtreecommitdiff
path: root/src/cmd/6g/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6g/cgen.c')
-rw-r--r--src/cmd/6g/cgen.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index b4ae1dfb9..7870a8f7e 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -136,6 +136,20 @@ cgen(Node *n, Node *res)
}
regalloc(&n1, nl->type, res);
cgen(nl, &n1);
+ if(isptrto(n->type, TARRAY) && isptrto(nl->type, TDARRAY)) {
+ // convert dynamic array to static array
+ n2 = n1;
+ n2.op = OINDREG;
+ n2.xoffset = offsetof(Array,array);
+ n2.type = types[tptr];
+ gins(AMOVQ, &n2, &n1);
+ }
+ if(isptrto(n->type, TDARRAY) && isptrto(nl->type, TARRAY)) {
+ // conver static array to dynamic array
+ // it is assumed that the dope is just before the array
+ nodconst(&n2, types[tptr], offsetof(Array,b));
+ gins(ASUBQ, &n2, &n1);
+ }
gmove(&n1, res);
regfree(&n1);
break;
@@ -173,9 +187,33 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
}
+ if(isptrto(nl->type, TDARRAY)) {
+ regalloc(&n1, types[tptr], res);
+ cgen(nl, &n1);
+ n1.op = OINDREG;
+ n1.type = types[TUINT32];
+ n1.xoffset = offsetof(Array,nel);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
fatal("cgen: OLEN: unknown type %lT", nl->type);
break;
+ case OCAP:
+ if(isptrto(nl->type, TDARRAY)) {
+ regalloc(&n1, types[tptr], res);
+ cgen(nl, &n1);
+ n1.op = OINDREG;
+ n1.type = types[TUINT32];
+ n1.xoffset = offsetof(Array,cap);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ fatal("cgen: OCAP: unknown type %lT", nl->type);
+ break;
+
case OADDR:
agen(nl, res);
break;
@@ -253,6 +291,7 @@ agen(Node *n, Node *res)
{
Node *nl, *nr;
Node n1, n2, n3, tmp;
+ Prog *p1;
uint32 w;
Type *t;
@@ -347,15 +386,60 @@ agen(Node *n, Node *res)
// &a is in res
// i is in &n1
// w is width
- nodconst(&n3, types[TINT64], w); // w/tint64
+
+ if(isptrto(nl->type, TDARRAY)) {
+ regalloc(&n2, types[tptr], res);
+ gmove(res, &n2);
+
+ if(!debug['B']) {
+ // check bounds
+ n3 = n2;
+ n3.op = OINDREG;
+ n3.type = types[tptr];
+ n3.xoffset = offsetof(Array, nel);
+ gins(optoas(OCMP, types[TUINT32]), &n1, &n3);
+
+ p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+
+ nodconst(&n3, types[TUINT8], 5); // 5 is range trap
+ gins(AINT, &n3, N);
+ patch(p1, pc);
+ }
+
+ // fetch array base from dope
+ n3 = n2;
+ n3.op = OINDREG;
+ n3.type = types[tptr];
+ n3.xoffset = offsetof(Array, array);
+ gins(AMOVQ, &n3, &n2);
+ gmove(&n2, res);
+ regfree(&n2);
+ } else
+ if(!debug['B']) {
+ // check bounds
+ nodconst(&n3, types[TUINT32], nl->type->bound);
+ if(isptrto(nl->type, TARRAY))
+ nodconst(&n3, types[TUINT32], nl->type->type->bound);
+ gins(optoas(OCMP, types[TUINT32]), &n1, &n3);
+
+ p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+
+ nodconst(&n3, types[TUINT8], 5); // 5 is range trap
+ gins(AINT, &n3, N);
+ patch(p1, pc);
+ }
+
+ t = types[TUINT64];
if(issigned[n1.type->etype])
- regalloc(&n2, types[TINT64], &n1); // i/int64
- else
- regalloc(&n2, types[TUINT64], &n1); // i/uint64
+ t = types[TINT64];
+
+ regalloc(&n2, t, &n1); // i
gmove(&n1, &n2);
- gins(optoas(OMUL, types[TINT64]), &n3, &n2);
- gins(optoas(OADD, types[tptr]), &n2, res);
regfree(&n1);
+
+ nodconst(&n3, t, w); // w
+ gins(optoas(OMUL, t), &n3, &n2);
+ gins(optoas(OADD, types[tptr]), &n2, res);
regfree(&n2);
break;