diff options
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r-- | src/cmd/5g/cgen.c | 95 |
1 files changed, 39 insertions, 56 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 1620f410a..2d260e72d 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -34,6 +34,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); @@ -77,6 +79,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; @@ -315,6 +318,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(AMOVW, 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. @@ -464,6 +483,16 @@ abop: // asymmetric binary cgen(nl, &n1); } gins(a, &n2, &n1); + // Normalize result for types smaller than word. + if(n->type->width < widthptr) { + switch(n->op) { + case OADD: + case OSUB: + case OMUL: + gins(optoas(OAS, n->type), &n1, &n1); + break; + } + } gmove(&n1, res); regfree(&n1); if(n2.op != OLITERAL) @@ -550,6 +579,7 @@ cgenindex(Node *n, Node *res, int bounded) /* * generate: * res = &n; + * The generated code checks that the result is not nil. */ void agen(Node *n, Node *res) @@ -629,6 +659,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); @@ -675,25 +707,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], N); - gmove(res, &n1); - regalloc(&n2, types[TUINT8], &n1); - n1.op = OINDREG; - n1.type = types[TUINT8]; - n1.xoffset = 0; - gmove(&n1, &n2); - regfree(&n1); - regfree(&n2); - } if(n->xoffset != 0) { nodconst(&n1, types[TINT32], n->xoffset); regalloc(&n2, n1.type, N); @@ -709,19 +727,7 @@ agen(Node *n, Node *res) case ODOTPTR: 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], N); - gmove(res, &n1); - regalloc(&n2, types[TUINT8], &n1); - n1.op = OINDREG; - n1.type = types[TUINT8]; - n1.xoffset = 0; - gmove(&n1, &n2); - regfree(&n1); - regfree(&n2); - } + cgen_checknil(res); if(n->xoffset != 0) { nodconst(&n1, types[TINT32], n->xoffset); regalloc(&n2, n1.type, N); @@ -747,11 +753,12 @@ ret: * * 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) { - Node n1, n2; + Node n1; int r; if(debug['g']) { @@ -792,19 +799,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) { - regalloc(&n1, types[tptr], N); - gmove(a, &n1); - regalloc(&n2, types[TUINT8], &n1); - n1.op = OINDREG; - n1.type = types[TUINT8]; - n1.xoffset = 0; - gmove(&n1, &n2); - regfree(&n1); - regfree(&n2); - } + cgen_checknil(a); a->op = OINDREG; a->xoffset = n->xoffset; a->type = n->type; @@ -894,6 +889,7 @@ cgenr(Node *n, Node *a, Node *res) * newreg = &n; * * caller must regfree(a). + * The generated code checks that the result is not nil. */ void agenr(Node *n, Node *a, Node *res) @@ -925,6 +921,7 @@ agenr(Node *n, Node *a, Node *res) case OIND: cgenr(n->left, a, res); + cgen_checknil(a); break; case OINDEX: @@ -966,20 +963,6 @@ agenr(Node *n, Node *a, Node *res) // i is in &n1 (if not constant) // 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) { - regalloc(&n4, types[tptr], N); - gmove(&n3, &n4); - regalloc(&tmp, types[TUINT8], &n4); - n4.op = OINDREG; - n4.type = types[TUINT8]; - n4.xoffset = 0; - gmove(&n4, &tmp); - regfree(&n4); - regfree(&tmp); - } - // constant index if(isconst(nr, CTINT)) { if(isconst(nl, CTSTR)) |