summaryrefslogtreecommitdiff
path: root/src/cmd/8g/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8g/cgen.c')
-rw-r--r--src/cmd/8g/cgen.c101
1 files changed, 56 insertions, 45 deletions
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index d54db7e62..cc28a3145 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -67,6 +67,8 @@ cgen(Node *n, Node *res)
case OSLICE:
case OSLICEARR:
case OSLICESTR:
+ case OSLICE3:
+ case OSLICE3ARR:
if (res->op != ONAME || !res->addable) {
tempname(&n1, n->type);
cgen_slice(n, &n1);
@@ -107,6 +109,7 @@ cgen(Node *n, Node *res)
// can't do in walk because n->left->addable
// changes if n->left is an escaping local variable.
switch(n->op) {
+ case OSPTR:
case OLEN:
if(isslice(n->left->type) || istype(n->left->type, TSTRING))
n->addable = n->left->addable;
@@ -286,6 +289,22 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
+ case OSPTR:
+ // pointer is the first word of string or slice.
+ if(isconst(nl, CTSTR)) {
+ regalloc(&n1, types[tptr], res);
+ p1 = gins(ALEAL, N, &n1);
+ datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ igen(nl, &n1, res);
+ n1.type = n->type;
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+
case OLEN:
if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
// map has len in the first 32-bit word.
@@ -474,12 +493,13 @@ igenindex(Node *n, Node *res, int bounded)
/*
* address gen
* res = &n;
+ * The generated code checks that the result is not nil.
*/
void
agen(Node *n, Node *res)
{
Node *nl, *nr;
- Node n1, n2, n3, n4, tmp, nlen;
+ Node n1, n2, n3, tmp, nlen;
Type *t;
uint32 w;
uint64 v;
@@ -547,6 +567,8 @@ agen(Node *n, Node *res)
case OSLICE:
case OSLICEARR:
case OSLICESTR:
+ case OSLICE3:
+ case OSLICE3ARR:
tempname(&n1, n->type);
cgen_slice(n, &n1);
agen(&n1, res);
@@ -602,16 +624,6 @@ agen(Node *n, Node *res)
// len(a) is in nlen (if needed)
// w is width
- // explicit check for nil if array is large enough
- // that we might derive too big a pointer.
- if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
- n4 = n3;
- n4.op = OINDREG;
- n4.type = types[TUINT8];
- n4.xoffset = 0;
- gins(ATESTB, nodintconst(0), &n4);
- }
-
// constant index
if(isconst(nr, CTINT)) {
if(isconst(nl, CTSTR))
@@ -735,23 +747,11 @@ agen(Node *n, Node *res)
case OIND:
cgen(nl, res);
+ cgen_checknil(res);
break;
case ODOT:
agen(nl, res);
- // explicit check for nil if struct is large enough
- // that we might derive too big a pointer. If the left node
- // was ODOT we have already done the nil check.
- if(nl->op != ODOT)
- if(nl->type->width >= unmappedzero) {
- regalloc(&n1, types[tptr], res);
- gmove(res, &n1);
- n1.op = OINDREG;
- n1.type = types[TUINT8];
- n1.xoffset = 0;
- gins(ATESTB, nodintconst(0), &n1);
- regfree(&n1);
- }
if(n->xoffset != 0) {
nodconst(&n1, types[tptr], n->xoffset);
gins(optoas(OADD, types[tptr]), &n1, res);
@@ -763,17 +763,7 @@ agen(Node *n, Node *res)
if(!isptr[t->etype])
fatal("agen: not ptr %N", n);
cgen(nl, res);
- // explicit check for nil if struct is large enough
- // that we might derive too big a pointer.
- if(nl->type->type->width >= unmappedzero) {
- regalloc(&n1, types[tptr], res);
- gmove(res, &n1);
- n1.op = OINDREG;
- n1.type = types[TUINT8];
- n1.xoffset = 0;
- gins(ATESTB, nodintconst(0), &n1);
- regfree(&n1);
- }
+ cgen_checknil(res);
if(n->xoffset != 0) {
nodconst(&n1, types[tptr], n->xoffset);
gins(optoas(OADD, types[tptr]), &n1, res);
@@ -789,6 +779,7 @@ agen(Node *n, Node *res)
*
* on exit, a has been changed to be *newreg.
* caller must regfree(a).
+ * The generated code checks that the result is not *nil.
*/
void
igen(Node *n, Node *a, Node *res)
@@ -838,15 +829,7 @@ igen(Node *n, Node *a, Node *res)
regalloc(a, types[tptr], res);
cgen(n->left, a);
}
- // explicit check for nil if struct is large enough
- // that we might derive too big a pointer.
- if(n->left->type->type->width >= unmappedzero) {
- n1 = *a;
- n1.op = OINDREG;
- n1.type = types[TUINT8];
- n1.xoffset = 0;
- gins(ATESTB, nodintconst(0), &n1);
- }
+ cgen_checknil(a);
a->op = OINDREG;
a->xoffset += n->xoffset;
a->type = n->type;
@@ -874,7 +857,35 @@ igen(Node *n, Node *a, Node *res)
a->xoffset = fp->width;
a->type = n->type;
return;
+
+ case OINDEX:
+ // Index of fixed-size array by constant can
+ // put the offset in the addressing.
+ // Could do the same for slice except that we need
+ // to use the real index for the bounds checking.
+ if(isfixedarray(n->left->type) ||
+ (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
+ if(isconst(n->right, CTINT)) {
+ // Compute &a.
+ if(!isptr[n->left->type->etype])
+ igen(n->left, a, res);
+ else {
+ igen(n->left, &n1, res);
+ cgen_checknil(&n1);
+ regalloc(a, types[tptr], res);
+ gmove(&n1, a);
+ regfree(&n1);
+ a->op = OINDREG;
+ }
+
+ // Compute &a[i] as &a + i*width.
+ a->type = n->type;
+ a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
+ return;
+ }
+ break;
}
+
// release register for now, to avoid
// confusing tempname.
if(res != N && res->op == OREGISTER)
@@ -1319,7 +1330,7 @@ cadable(Node *n)
* copy a composite value by moving its individual components.
* Slices, strings and interfaces are supported.
* nr is N when assigning a zero value.
- * return 1 if can do, 0 if cant.
+ * return 1 if can do, 0 if can't.
*/
int
componentgen(Node *nr, Node *nl)