summaryrefslogtreecommitdiff
path: root/src/cmd/5g/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r--src/cmd/5g/cgen.c95
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))