regalloc(&n2, n->type, &n1);
n1.op = OINDREG;
n1.type = n->type;
- n1.xoffset = 0;
+ n1.xoffset += 0;
gmove(&n1, &n2);
gmove(&n2, res);
regfree(&n1);
regalloc(&n2, types[TUINT32], &n1);
n1.op = OINDREG;
n1.type = types[TUINT32];
- n1.xoffset = Array_nel;
+ n1.xoffset += Array_nel;
gmove(&n1, &n2);
gmove(&n2, res);
regfree(&n1);
// Pick it up again after the call.
rg = -1;
if(n->ullman >= UINF) {
- if(res->op == OREGISTER || res->op == OINDREG) {
+ if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
rg = res->val.u.reg;
reg[rg]--;
}
void
igen(Node *n, Node *a, Node *res)
{
+ Node n1;
+ Prog *p1;
+ int r;
+
+ if(debug['g']) {
+ dump("\nigen-n", n);
+ }
+ switch(n->op) {
+ case ODOT:
+ igen(n->left, a, res);
+ a->xoffset += n->xoffset;
+ a->type = n->type;
+ return;
+
+ case ODOTPTR:
+ if(n->left->addable
+ || n->left->op == OCALLFUNC
+ || n->left->op == OCALLMETH
+ || n->left->op == OCALLINTER) {
+ // igen-able nodes.
+ igen(n->left, &n1, res);
+ regalloc(a, types[tptr], &n1);
+ gmove(&n1, a);
+ regfree(&n1);
+ } else {
+ regalloc(a, types[tptr], res);
+ cgen(n->left, a);
+ }
+ if(n->xoffset != 0) {
+ // 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);
+ p1 = gins(AMOVW, &n1, &n1);
+ p1->from.type = D_OREG;
+ p1->from.offset = 0;
+ regfree(&n1);
+ }
+ }
+ a->op = OINDREG;
+ a->xoffset = n->xoffset;
+ a->type = n->type;
+ return;
+
+ case OCALLMETH:
+ case OCALLFUNC:
+ case OCALLINTER:
+ // Release res so that it is available for cgen_call.
+ // Pick it up again after the call.
+ r = -1;
+ if(n->ullman >= UINF) {
+ if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
+ r = res->val.u.reg;
+ reg[r]--;
+ }
+ }
+ switch(n->op) {
+ case OCALLMETH:
+ cgen_callmeth(n, 0);
+ break;
+ case OCALLFUNC:
+ cgen_call(n, 0);
+ break;
+ case OCALLINTER:
+ cgen_callinter(n, N, 0);
+ break;
+ }
+ if(r >= 0)
+ reg[r]++;
+ regalloc(a, types[tptr], res);
+ cgen_aret(n, a);
+ a->op = OINDREG;
+ a->type = n->type;
+ return;
+ }
+
regalloc(a, types[tptr], res);
agen(n, a);
a->op = OINDREG;
void
agenr(Node *n, Node *a, Node *res)
{
- regalloc(a, types[tptr], res);
- agen(n, a);
+ Node n1;
+
+ igen(n, &n1, res);
+ regalloc(a, types[tptr], N);
+ agen(&n1, a);
+ regfree(&n1);
}
void
cgen(nr, &n1);
}
if(!isconst(nl, CTSTR)) {
- regalloc(&n3, types[tptr], res);
- if(isfixedarray(nl->type))
+ if(isfixedarray(nl->type)) {
+ regalloc(&n3, types[tptr], res);
agen(nl, &n3);
- else {
+ } else {
igen(nl, &nlen, res);
nlen.type = types[tptr];
nlen.xoffset += Array_array;
+ regalloc(&n3, types[tptr], res);
gmove(&nlen, &n3);
nlen.type = types[simtype[TUINT]];
nlen.xoffset += Array_nel-Array_array;
nr = &tmp;
irad:
if(!isconst(nl, CTSTR)) {
- regalloc(&n3, types[tptr], res);
- if(isfixedarray(nl->type))
+ if(isfixedarray(nl->type)) {
+ regalloc(&n3, types[tptr], res);
agen(nl, &n3);
- else {
+ } else {
if(!nl->addable) {
// igen will need an addressable node.
tempname(&tmp2, nl->type);
igen(nl, &nlen, res);
nlen.type = types[tptr];
nlen.xoffset += Array_array;
+ regalloc(&n3, types[tptr], res);
gmove(&nlen, &n3);
nlen.type = types[simtype[TUINT]];
nlen.xoffset += Array_nel-Array_array;
{
Type *fp;
Iter flist;
- Node n1, n2;
+ Node n1;
+ if(debug['g']) {
+ dump("\nigen-n", n);
+ }
switch(n->op) {
case ONAME:
if((n->class&PHEAP) || n->class == PPARAMREF)
return;
case ODOTPTR:
- regalloc(a, types[tptr], res);
- cgen(n->left, a);
+ if(n->left->addable
+ || n->left->op == OCALLFUNC
+ || n->left->op == OCALLMETH
+ || n->left->op == OCALLINTER) {
+ // igen-able nodes.
+ igen(n->left, &n1, res);
+ regalloc(a, types[tptr], &n1);
+ gmove(&n1, a);
+ regfree(&n1);
+ } else {
+ regalloc(a, types[tptr], res);
+ cgen(n->left, a);
+ }
if(n->xoffset != 0) {
// explicit check for nil if struct is large enough
// that we might derive too big a pointer.
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.
if(isfixedarray(n->left->type) ||
(isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
if(isconst(n->right, CTINT)) {
- nodconst(&n1, types[TINT64], 0);
- n2 = *n;
- n2.right = &n1;
+ // Compute &a.
+ if(!isptr[n->left->type->etype])
+ igen(n->left, a, res);
+ else {
+ igen(n->left, &n1, res);
+ regalloc(a, types[tptr], res);
+ gmove(&n1, a);
+ regfree(&n1);
+ a->op = OINDREG;
+ }
- regalloc(a, types[tptr], res);
- agen(&n2, a);
- a->op = OINDREG;
- a->xoffset = mpgetfix(n->right->val.u.xval)*n->type->width;
+ // Compute &a[i] as &a + i*width.
a->type = n->type;
+ a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
return;
}
-
}
regalloc(a, types[tptr], res);
Iter flist;
Node n1;
+ if(debug['g']) {
+ dump("\nigen-n", n);
+ }
switch(n->op) {
case ONAME:
if((n->class&PHEAP) || n->class == PPARAMREF)
return;
case ODOTPTR:
- regalloc(a, types[tptr], res);
- cgen(n->left, a);
+ if(n->left->addable
+ || n->left->op == OCALLFUNC
+ || n->left->op == OCALLMETH
+ || n->left->op == OCALLINTER) {
+ // igen-able nodes.
+ igen(n->left, &n1, res);
+ regalloc(a, types[tptr], &n1);
+ gmove(&n1, a);
+ regfree(&n1);
+ } else {
+ regalloc(a, types[tptr], res);
+ cgen(n->left, a);
+ }
if(n->xoffset != 0) {
// explicit check for nil if struct is large enough
// that we might derive too big a pointer.
Child(0).(*U)
}
+// Type assertions and slice indexing. See issue 4207.
+func ChainAssertIndex(u *U) J {
+ return u.
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0]
+}
+
+type UArr struct {
+ Children [2]J
+}
+
+func (u *UArr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayIndex(u *UArr) J {
+ return u.
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ // Children[0].(*UArr).
+ // Children[0].(*UArr).
+ // Children[0].(*UArr).
+ // Children[0].(*UArr).
+ // Children[0].(*UArr).
+ // Children[0].(*UArr).
+ Children[0]
+}
+
+type UArrPtr struct {
+ Children *[2]J
+}
+
+func (u *UArrPtr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayptrIndex(u *UArrPtr) J {
+ // TODO: don't crash on longer chains.
+ return u.
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ // Children[0].(*UArrPtr).
+ Children[0]
+}
+
// Chains of divisions. See issue 4201.
func ChainDiv(a, b int) int {
func ChainDivRight(a, b int) int {
return a / (b / (a / (b /
- (a / (b / (a / (b /
- (a / (b / (a / (b /
- (a / (b / (a / (b /
- (a / (b / (a / b))))))))))))))))))
+ (a / (b / (a / (b /
+ (a / (b / (a / (b /
+ (a / (b / (a / (b /
+ (a / (b / (a / b))))))))))))))))))
}
func ChainDivConst(a int) int {