github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/8g/cgen.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // TODO(rsc):
     6  //	assume CLD?
     7  
     8  #include <u.h>
     9  #include <libc.h>
    10  #include "gg.h"
    11  
    12  void
    13  mgen(Node *n, Node *n1, Node *rg)
    14  {
    15  	Node n2;
    16  
    17  	n1->op = OEMPTY;
    18  
    19  	if(n->addable) {
    20  		*n1 = *n;
    21  		if(n1->op == OREGISTER || n1->op == OINDREG)
    22  			reg[n->val.u.reg]++;
    23  		return;
    24  	}
    25  	tempname(n1, n->type);
    26  	cgen(n, n1);
    27  	if(n->type->width <= widthptr || isfloat[n->type->etype]) {
    28  		n2 = *n1;
    29  		regalloc(n1, n->type, rg);
    30  		gmove(&n2, n1);
    31  	}
    32  }
    33  
    34  void
    35  mfree(Node *n)
    36  {
    37  	if(n->op == OREGISTER)
    38  		regfree(n);
    39  }
    40  
    41  /*
    42   * generate:
    43   *	res = n;
    44   * simplifies and calls gmove.
    45   *
    46   * TODO:
    47   *	sudoaddable
    48   */
    49  void
    50  cgen(Node *n, Node *res)
    51  {
    52  	Node *nl, *nr, *r, n1, n2, nt;
    53  	Prog *p1, *p2, *p3;
    54  	int a;
    55  
    56  	if(debug['g']) {
    57  		dump("\ncgen-n", n);
    58  		dump("cgen-res", res);
    59  	}
    60  
    61  	if(n == N || n->type == T)
    62  		fatal("cgen: n nil");
    63  	if(res == N || res->type == T)
    64  		fatal("cgen: res nil");
    65  
    66  	switch(n->op) {
    67  	case OSLICE:
    68  	case OSLICEARR:
    69  	case OSLICESTR:
    70  	case OSLICE3:
    71  	case OSLICE3ARR:
    72  		if (res->op != ONAME || !res->addable) {
    73  			tempname(&n1, n->type);
    74  			cgen_slice(n, &n1);
    75  			cgen(&n1, res);
    76  		} else
    77  			cgen_slice(n, res);
    78  		return;
    79  	case OEFACE:
    80  		if (res->op != ONAME || !res->addable) {
    81  			tempname(&n1, n->type);
    82  			cgen_eface(n, &n1);
    83  			cgen(&n1, res);
    84  		} else
    85  			cgen_eface(n, res);
    86  		return;
    87  	}
    88  
    89  	while(n->op == OCONVNOP)
    90  		n = n->left;
    91  
    92  	// function calls on both sides?  introduce temporary
    93  	if(n->ullman >= UINF && res->ullman >= UINF) {
    94  		tempname(&n1, n->type);
    95  		cgen(n, &n1);
    96  		cgen(&n1, res);
    97  		return;
    98  	}
    99  
   100  	// structs etc get handled specially
   101  	if(isfat(n->type)) {
   102  		if(n->type->width < 0)
   103  			fatal("forgot to compute width for %T", n->type);
   104  		sgen(n, res, n->type->width);
   105  		return;
   106  	}
   107  
   108  	// update addressability for string, slice
   109  	// can't do in walk because n->left->addable
   110  	// changes if n->left is an escaping local variable.
   111  	switch(n->op) {
   112  	case OSPTR:
   113  	case OLEN:
   114  		if(isslice(n->left->type) || istype(n->left->type, TSTRING))
   115  			n->addable = n->left->addable;
   116  		break;
   117  	case OCAP:
   118  		if(isslice(n->left->type))
   119  			n->addable = n->left->addable;
   120  		break;
   121  	case OITAB:
   122  		n->addable = n->left->addable;
   123  		break;
   124  	}
   125  
   126  	// if both are addressable, move
   127  	if(n->addable && res->addable) {
   128  		gmove(n, res);
   129  		return;
   130  	}
   131  
   132  	// if both are not addressable, use a temporary.
   133  	if(!n->addable && !res->addable) {
   134  		// could use regalloc here sometimes,
   135  		// but have to check for ullman >= UINF.
   136  		tempname(&n1, n->type);
   137  		cgen(n, &n1);
   138  		cgen(&n1, res);
   139  		return;
   140  	}
   141  
   142  	// if result is not addressable directly but n is,
   143  	// compute its address and then store via the address.
   144  	if(!res->addable) {
   145  		igen(res, &n1, N);
   146  		cgen(n, &n1);
   147  		regfree(&n1);
   148  		return;
   149  	}
   150  
   151  	// complex types
   152  	if(complexop(n, res)) {
   153  		complexgen(n, res);
   154  		return;
   155  	}
   156  
   157  	// otherwise, the result is addressable but n is not.
   158  	// let's do some computation.
   159  
   160  	// use ullman to pick operand to eval first.
   161  	nl = n->left;
   162  	nr = n->right;
   163  	if(nl != N && nl->ullman >= UINF)
   164  	if(nr != N && nr->ullman >= UINF) {
   165  		// both are hard
   166  		tempname(&n1, nl->type);
   167  		cgen(nl, &n1);
   168  		n2 = *n;
   169  		n2.left = &n1;
   170  		cgen(&n2, res);
   171  		return;
   172  	}
   173  
   174  	// 64-bit ops are hard on 32-bit machine.
   175  	if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
   176  		switch(n->op) {
   177  		// math goes to cgen64.
   178  		case OMINUS:
   179  		case OCOM:
   180  		case OADD:
   181  		case OSUB:
   182  		case OMUL:
   183  		case OLROT:
   184  		case OLSH:
   185  		case ORSH:
   186  		case OAND:
   187  		case OOR:
   188  		case OXOR:
   189  			cgen64(n, res);
   190  			return;
   191  		}
   192  	}
   193  
   194  	if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) {
   195  		cgen_float(n, res);
   196  		return;
   197  	}
   198  
   199  	switch(n->op) {
   200  	default:
   201  		dump("cgen", n);
   202  		fatal("cgen %O", n->op);
   203  		break;
   204  
   205  	case OREAL:
   206  	case OIMAG:
   207  	case OCOMPLEX:
   208  		fatal("unexpected complex");
   209  		return;
   210  
   211  	// these call bgen to get a bool value
   212  	case OOROR:
   213  	case OANDAND:
   214  	case OEQ:
   215  	case ONE:
   216  	case OLT:
   217  	case OLE:
   218  	case OGE:
   219  	case OGT:
   220  	case ONOT:
   221  		p1 = gbranch(AJMP, T, 0);
   222  		p2 = pc;
   223  		gmove(nodbool(1), res);
   224  		p3 = gbranch(AJMP, T, 0);
   225  		patch(p1, pc);
   226  		bgen(n, 1, 0, p2);
   227  		gmove(nodbool(0), res);
   228  		patch(p3, pc);
   229  		return;
   230  
   231  	case OPLUS:
   232  		cgen(nl, res);
   233  		return;
   234  
   235  	case OMINUS:
   236  	case OCOM:
   237  		a = optoas(n->op, nl->type);
   238  		goto uop;
   239  
   240  	// symmetric binary
   241  	case OAND:
   242  	case OOR:
   243  	case OXOR:
   244  	case OADD:
   245  	case OADDPTR:
   246  	case OMUL:
   247  		a = optoas(n->op, nl->type);
   248  		if(a == AIMULB) {
   249  			cgen_bmul(n->op, nl, nr, res);
   250  			break;
   251  		}
   252  		goto sbop;
   253  
   254  	// asymmetric binary
   255  	case OSUB:
   256  		a = optoas(n->op, nl->type);
   257  		goto abop;
   258  
   259  	case OHMUL:
   260  		cgen_hmul(nl, nr, res);
   261  		break;
   262  
   263  	case OCONV:
   264  		if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
   265  			cgen(nl, res);
   266  			break;
   267  		}
   268  
   269  		tempname(&n2, n->type);
   270  		mgen(nl, &n1, res);
   271  		gmove(&n1, &n2);
   272  		gmove(&n2, res);
   273  		mfree(&n1);
   274  		break;
   275  
   276  	case ODOT:
   277  	case ODOTPTR:
   278  	case OINDEX:
   279  	case OIND:
   280  	case ONAME:	// PHEAP or PPARAMREF var
   281  		igen(n, &n1, res);
   282  		gmove(&n1, res);
   283  		regfree(&n1);
   284  		break;
   285  
   286  	case OITAB:
   287  		igen(nl, &n1, res);
   288  		n1.type = ptrto(types[TUINTPTR]);
   289  		gmove(&n1, res);
   290  		regfree(&n1);
   291  		break;
   292  
   293  	case OSPTR:
   294  		// pointer is the first word of string or slice.
   295  		if(isconst(nl, CTSTR)) {
   296  			regalloc(&n1, types[tptr], res);
   297  			p1 = gins(ALEAL, N, &n1);
   298  			datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
   299  			gmove(&n1, res);
   300  			regfree(&n1);
   301  			break;
   302  		}
   303  		igen(nl, &n1, res);
   304  		n1.type = n->type;
   305  		gmove(&n1, res);
   306  		regfree(&n1);
   307  		break;
   308  
   309  	case OLEN:
   310  		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
   311  			// map has len in the first 32-bit word.
   312  			// a zero pointer means zero length
   313  			tempname(&n1, types[tptr]);
   314  			cgen(nl, &n1);
   315  			regalloc(&n2, types[tptr], N);
   316  			gmove(&n1, &n2);
   317  			n1 = n2;
   318  
   319  			nodconst(&n2, types[tptr], 0);
   320  			gins(optoas(OCMP, types[tptr]), &n1, &n2);
   321  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   322  
   323  			n2 = n1;
   324  			n2.op = OINDREG;
   325  			n2.type = types[TINT32];
   326  			gmove(&n2, &n1);
   327  
   328  			patch(p1, pc);
   329  
   330  			gmove(&n1, res);
   331  			regfree(&n1);
   332  			break;
   333  		}
   334  		if(istype(nl->type, TSTRING) || isslice(nl->type)) {
   335  			// both slice and string have len one pointer into the struct.
   336  			igen(nl, &n1, res);
   337  			n1.type = types[TUINT32];
   338  			n1.xoffset += Array_nel;
   339  			gmove(&n1, res);
   340  			regfree(&n1);
   341  			break;
   342  		}
   343  		fatal("cgen: OLEN: unknown type %lT", nl->type);
   344  		break;
   345  
   346  	case OCAP:
   347  		if(istype(nl->type, TCHAN)) {
   348  			// chan has cap in the second 32-bit word.
   349  			// a zero pointer means zero length
   350  			regalloc(&n1, types[tptr], res);
   351  			cgen(nl, &n1);
   352  
   353  			nodconst(&n2, types[tptr], 0);
   354  			gins(optoas(OCMP, types[tptr]), &n1, &n2);
   355  			p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
   356  
   357  			n2 = n1;
   358  			n2.op = OINDREG;
   359  			n2.xoffset = 4;
   360  			n2.type = types[TINT32];
   361  			gmove(&n2, &n1);
   362  
   363  			patch(p1, pc);
   364  
   365  			gmove(&n1, res);
   366  			regfree(&n1);
   367  			break;
   368  		}
   369  		if(isslice(nl->type)) {
   370  			igen(nl, &n1, res);
   371  			n1.type = types[TUINT32];
   372  			n1.xoffset += Array_cap;
   373  			gmove(&n1, res);
   374  			regfree(&n1);
   375  			break;
   376  		}
   377  		fatal("cgen: OCAP: unknown type %lT", nl->type);
   378  		break;
   379  
   380  	case OADDR:
   381  		agen(nl, res);
   382  		break;
   383  
   384  	case OCALLMETH:
   385  		cgen_callmeth(n, 0);
   386  		cgen_callret(n, res);
   387  		break;
   388  
   389  	case OCALLINTER:
   390  		cgen_callinter(n, res, 0);
   391  		cgen_callret(n, res);
   392  		break;
   393  
   394  	case OCALLFUNC:
   395  		cgen_call(n, 0);
   396  		cgen_callret(n, res);
   397  		break;
   398  
   399  	case OMOD:
   400  	case ODIV:
   401  		cgen_div(n->op, nl, nr, res);
   402  		break;
   403  
   404  	case OLSH:
   405  	case ORSH:
   406  	case OLROT:
   407  		cgen_shift(n->op, n->bounded, nl, nr, res);
   408  		break;
   409  	}
   410  	return;
   411  
   412  sbop:	// symmetric binary
   413  	if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
   414  		r = nl;
   415  		nl = nr;
   416  		nr = r;
   417  	}
   418  
   419  abop:	// asymmetric binary
   420  	if(smallintconst(nr)) {
   421  		mgen(nl, &n1, res);
   422  		regalloc(&n2, nl->type, &n1);
   423  		gmove(&n1, &n2);
   424  		gins(a, nr, &n2);
   425  		gmove(&n2, res);
   426  		regfree(&n2);
   427  		mfree(&n1);
   428  	} else if(nl->ullman >= nr->ullman) {
   429  		tempname(&nt, nl->type);
   430  		cgen(nl, &nt);
   431  		mgen(nr, &n2, N);
   432  		regalloc(&n1, nl->type, res);
   433  		gmove(&nt, &n1);
   434  		gins(a, &n2, &n1);
   435  		gmove(&n1, res);
   436  		regfree(&n1);
   437  		mfree(&n2);
   438  	} else {
   439  		regalloc(&n2, nr->type, res);
   440  		cgen(nr, &n2);
   441  		regalloc(&n1, nl->type, N);
   442  		cgen(nl, &n1);
   443  		gins(a, &n2, &n1);
   444  		regfree(&n2);
   445  		gmove(&n1, res);
   446  		regfree(&n1);
   447  	}
   448  	return;
   449  
   450  uop:	// unary
   451  	tempname(&n1, nl->type);
   452  	cgen(nl, &n1);
   453  	gins(a, N, &n1);
   454  	gmove(&n1, res);
   455  	return;
   456  }
   457  
   458  /*
   459   * generate an addressable node in res, containing the value of n.
   460   * n is an array index, and might be any size; res width is <= 32-bit.
   461   * returns Prog* to patch to panic call.
   462   */
   463  static Prog*
   464  igenindex(Node *n, Node *res, int bounded)
   465  {
   466  	Node tmp, lo, hi, zero;
   467  
   468  	if(!is64(n->type)) {
   469  		if(n->addable) {
   470  			// nothing to do.
   471  			*res = *n;
   472  		} else {
   473  			tempname(res, types[TUINT32]);
   474  			cgen(n, res);
   475  		}
   476  		return nil;
   477  	}
   478  
   479  	tempname(&tmp, types[TINT64]);
   480  	cgen(n, &tmp);
   481  	split64(&tmp, &lo, &hi);
   482  	tempname(res, types[TUINT32]);
   483  	gmove(&lo, res);
   484  	if(bounded) {
   485  		splitclean();
   486  		return nil;
   487  	}
   488  	nodconst(&zero, types[TINT32], 0);
   489  	gins(ACMPL, &hi, &zero);
   490  	splitclean();
   491  	return gbranch(AJNE, T, +1);
   492  }
   493  		
   494  /*
   495   * address gen
   496   *	res = &n;
   497   * The generated code checks that the result is not nil.
   498   */
   499  void
   500  agen(Node *n, Node *res)
   501  {
   502  	Node *nl, *nr;
   503  	Node n1, n2, n3, tmp, nlen;
   504  	Type *t;
   505  	uint32 w;
   506  	uint64 v;
   507  	Prog *p1, *p2;
   508  	int bounded;
   509  
   510  	if(debug['g']) {
   511  		dump("\nagen-res", res);
   512  		dump("agen-r", n);
   513  	}
   514  	if(n == N || n->type == T || res == N || res->type == T)
   515  		fatal("agen");
   516  
   517  	while(n->op == OCONVNOP)
   518  		n = n->left;
   519  
   520  	if(isconst(n, CTNIL) && n->type->width > widthptr) {
   521  		// Use of a nil interface or nil slice.
   522  		// Create a temporary we can take the address of and read.
   523  		// The generated code is just going to panic, so it need not
   524  		// be terribly efficient. See issue 3670.
   525  		tempname(&n1, n->type);
   526  		gvardef(&n1);
   527  		clearfat(&n1);
   528  		regalloc(&n2, types[tptr], res);
   529  		gins(ALEAL, &n1, &n2);
   530  		gmove(&n2, res);
   531  		regfree(&n2);
   532  		return;
   533  	}
   534  		
   535  	// addressable var is easy
   536  	if(n->addable) {
   537  		if(n->op == OREGISTER)
   538  			fatal("agen OREGISTER");
   539  		regalloc(&n1, types[tptr], res);
   540  		gins(ALEAL, n, &n1);
   541  		gmove(&n1, res);
   542  		regfree(&n1);
   543  		return;
   544  	}
   545  
   546  	// let's compute
   547  	nl = n->left;
   548  	nr = n->right;
   549  
   550  	switch(n->op) {
   551  	default:
   552  		fatal("agen %O", n->op);
   553  
   554  	case OCALLMETH:
   555  		cgen_callmeth(n, 0);
   556  		cgen_aret(n, res);
   557  		break;
   558  
   559  	case OCALLINTER:
   560  		cgen_callinter(n, res, 0);
   561  		cgen_aret(n, res);
   562  		break;
   563  
   564  	case OCALLFUNC:
   565  		cgen_call(n, 0);
   566  		cgen_aret(n, res);
   567  		break;
   568  
   569  	case OSLICE:
   570  	case OSLICEARR:
   571  	case OSLICESTR:
   572  	case OSLICE3:
   573  	case OSLICE3ARR:
   574  		tempname(&n1, n->type);
   575  		cgen_slice(n, &n1);
   576  		agen(&n1, res);
   577  		break;
   578  
   579  	case OEFACE:
   580  		tempname(&n1, n->type);
   581  		cgen_eface(n, &n1);
   582  		agen(&n1, res);
   583  		break;
   584  
   585  	case OINDEX:
   586  		p2 = nil;  // to be patched to panicindex.
   587  		w = n->type->width;
   588  		bounded = debug['B'] || n->bounded;
   589  		if(nr->addable) {
   590  			// Generate &nl first, and move nr into register.
   591  			if(!isconst(nl, CTSTR))
   592  				igen(nl, &n3, res);
   593  			if(!isconst(nr, CTINT)) {
   594  				p2 = igenindex(nr, &tmp, bounded);
   595  				regalloc(&n1, tmp.type, N);
   596  				gmove(&tmp, &n1);
   597  			}
   598  		} else if(nl->addable) {
   599  			// Generate nr first, and move &nl into register.
   600  			if(!isconst(nr, CTINT)) {
   601  				p2 = igenindex(nr, &tmp, bounded);
   602  				regalloc(&n1, tmp.type, N);
   603  				gmove(&tmp, &n1);
   604  			}
   605  			if(!isconst(nl, CTSTR))
   606  				igen(nl, &n3, res);
   607  		} else {
   608  			p2 = igenindex(nr, &tmp, bounded);
   609  			nr = &tmp;
   610  			if(!isconst(nl, CTSTR))
   611  				igen(nl, &n3, res);
   612  			regalloc(&n1, tmp.type, N);
   613  			gins(optoas(OAS, tmp.type), &tmp, &n1);
   614  		}
   615  
   616  		// For fixed array we really want the pointer in n3.
   617  		if(isfixedarray(nl->type)) {
   618  			regalloc(&n2, types[tptr], &n3);
   619  			agen(&n3, &n2);
   620  			regfree(&n3);
   621  			n3 = n2;
   622  		}
   623  
   624  		// &a[0] is in n3 (allocated in res)
   625  		// i is in n1 (if not constant)
   626  		// len(a) is in nlen (if needed)
   627  		// w is width
   628  
   629  		// constant index
   630  		if(isconst(nr, CTINT)) {
   631  			if(isconst(nl, CTSTR))
   632  				fatal("constant string constant index");  // front end should handle
   633  			v = mpgetfix(nr->val.u.xval);
   634  			if(isslice(nl->type) || nl->type->etype == TSTRING) {
   635  				if(!debug['B'] && !n->bounded) {
   636  					nlen = n3;
   637  					nlen.type = types[TUINT32];
   638  					nlen.xoffset += Array_nel;
   639  					nodconst(&n2, types[TUINT32], v);
   640  					gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
   641  					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
   642  					ginscall(panicindex, -1);
   643  					patch(p1, pc);
   644  				}
   645  			}
   646  
   647  			// Load base pointer in n2 = n3.
   648  			regalloc(&n2, types[tptr], &n3);
   649  			n3.type = types[tptr];
   650  			n3.xoffset += Array_array;
   651  			gmove(&n3, &n2);
   652  			regfree(&n3);
   653  			if (v*w != 0) {
   654  				nodconst(&n1, types[tptr], v*w);
   655  				gins(optoas(OADD, types[tptr]), &n1, &n2);
   656  			}
   657  			gmove(&n2, res);
   658  			regfree(&n2);
   659  			break;
   660  		}
   661  
   662  		// i is in register n1, extend to 32 bits.
   663  		t = types[TUINT32];
   664  		if(issigned[n1.type->etype])
   665  			t = types[TINT32];
   666  
   667  		regalloc(&n2, t, &n1);			// i
   668  		gmove(&n1, &n2);
   669  		regfree(&n1);
   670  
   671  		if(!debug['B'] && !n->bounded) {
   672  			// check bounds
   673  			t = types[TUINT32];
   674  			if(isconst(nl, CTSTR)) {
   675  				nodconst(&nlen, t, nl->val.u.sval->len);
   676  			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
   677  				nlen = n3;
   678  				nlen.type = t;
   679  				nlen.xoffset += Array_nel;
   680  			} else {
   681  				nodconst(&nlen, t, nl->type->bound);
   682  			}
   683  			gins(optoas(OCMP, t), &n2, &nlen);
   684  			p1 = gbranch(optoas(OLT, t), T, +1);
   685  			if(p2)
   686  				patch(p2, pc);
   687  			ginscall(panicindex, -1);
   688  			patch(p1, pc);
   689  		}
   690  
   691  		if(isconst(nl, CTSTR)) {
   692  			regalloc(&n3, types[tptr], res);
   693  			p1 = gins(ALEAL, N, &n3);
   694  			datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
   695  			p1->from.scale = 1;
   696  			p1->from.index = n2.val.u.reg;
   697  			goto indexdone;
   698  		}
   699  
   700  		// Load base pointer in n3.
   701  		regalloc(&tmp, types[tptr], &n3);
   702  		if(isslice(nl->type) || nl->type->etype == TSTRING) {
   703  			n3.type = types[tptr];
   704  			n3.xoffset += Array_array;
   705  			gmove(&n3, &tmp);
   706  		}
   707  		regfree(&n3);
   708  		n3 = tmp;
   709  
   710  		if(w == 0) {
   711  			// nothing to do
   712  		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
   713  			// LEAL (n3)(n2*w), n3
   714  			p1 = gins(ALEAL, &n2, &n3);
   715  			p1->from.scale = w;
   716  			p1->from.index = p1->from.type;
   717  			p1->from.type = p1->to.type + D_INDIR;
   718  		} else {
   719  			nodconst(&tmp, types[TUINT32], w);
   720  			gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
   721  			gins(optoas(OADD, types[tptr]), &n2, &n3);
   722  		}
   723  
   724  	indexdone:
   725  		gmove(&n3, res);
   726  		regfree(&n2);
   727  		regfree(&n3);
   728  		break;
   729  
   730  	case ONAME:
   731  		// should only get here with names in this func.
   732  		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
   733  			dump("bad agen", n);
   734  			fatal("agen: bad ONAME funcdepth %d != %d",
   735  				n->funcdepth, funcdepth);
   736  		}
   737  
   738  		// should only get here for heap vars or paramref
   739  		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
   740  			dump("bad agen", n);
   741  			fatal("agen: bad ONAME class %#x", n->class);
   742  		}
   743  		cgen(n->heapaddr, res);
   744  		if(n->xoffset != 0) {
   745  			nodconst(&n1, types[tptr], n->xoffset);
   746  			gins(optoas(OADD, types[tptr]), &n1, res);
   747  		}
   748  		break;
   749  
   750  	case OIND:
   751  		cgen(nl, res);
   752  		cgen_checknil(res);
   753  		break;
   754  
   755  	case ODOT:
   756  		agen(nl, res);
   757  		if(n->xoffset != 0) {
   758  			nodconst(&n1, types[tptr], n->xoffset);
   759  			gins(optoas(OADD, types[tptr]), &n1, res);
   760  		}
   761  		break;
   762  
   763  	case ODOTPTR:
   764  		t = nl->type;
   765  		if(!isptr[t->etype])
   766  			fatal("agen: not ptr %N", n);
   767  		cgen(nl, res);
   768  		cgen_checknil(res);
   769  		if(n->xoffset != 0) {
   770  			nodconst(&n1, types[tptr], n->xoffset);
   771  			gins(optoas(OADD, types[tptr]), &n1, res);
   772  		}
   773  		break;
   774  	}
   775  }
   776  
   777  /*
   778   * generate:
   779   *	newreg = &n;
   780   *	res = newreg
   781   *
   782   * on exit, a has been changed to be *newreg.
   783   * caller must regfree(a).
   784   * The generated code checks that the result is not *nil.
   785   */
   786  void
   787  igen(Node *n, Node *a, Node *res)
   788  {
   789  	Type *fp;
   790  	Iter flist;
   791  	Node n1;
   792  
   793  	if(debug['g']) {
   794  		dump("\nigen-n", n);
   795  	}
   796  	switch(n->op) {
   797  	case ONAME:
   798  		if((n->class&PHEAP) || n->class == PPARAMREF)
   799  			break;
   800  		*a = *n;
   801  		return;
   802  
   803  	case OINDREG:
   804  		// Increase the refcount of the register so that igen's caller
   805  		// has to call regfree.
   806  		if(n->val.u.reg != D_SP)
   807  			reg[n->val.u.reg]++;
   808  		*a = *n;
   809  		return;
   810  
   811  	case ODOT:
   812  		igen(n->left, a, res);
   813  		a->xoffset += n->xoffset;
   814  		a->type = n->type;
   815  		return;
   816  
   817  	case ODOTPTR:
   818  		switch(n->left->op) {
   819  		case ODOT:
   820  		case ODOTPTR:
   821  		case OCALLFUNC:
   822  		case OCALLMETH:
   823  		case OCALLINTER:
   824  			// igen-able nodes.
   825  			igen(n->left, &n1, res);
   826  			regalloc(a, types[tptr], &n1);
   827  			gmove(&n1, a);
   828  			regfree(&n1);
   829  			break;
   830  		default:
   831  			regalloc(a, types[tptr], res);
   832  			cgen(n->left, a);
   833  		}
   834  		cgen_checknil(a);
   835  		a->op = OINDREG;
   836  		a->xoffset += n->xoffset;
   837  		a->type = n->type;
   838  		return;
   839  
   840  	case OCALLFUNC:
   841  	case OCALLMETH:
   842  	case OCALLINTER:
   843  		switch(n->op) {
   844  		case OCALLFUNC:
   845  			cgen_call(n, 0);
   846  			break;
   847  		case OCALLMETH:
   848  			cgen_callmeth(n, 0);
   849  			break;
   850  		case OCALLINTER:
   851  			cgen_callinter(n, N, 0);
   852  			break;
   853  		}
   854  		fp = structfirst(&flist, getoutarg(n->left->type));
   855  		memset(a, 0, sizeof *a);
   856  		a->op = OINDREG;
   857  		a->val.u.reg = D_SP;
   858  		a->addable = 1;
   859  		a->xoffset = fp->width;
   860  		a->type = n->type;
   861  		return;
   862  
   863  	case OINDEX:
   864  		// Index of fixed-size array by constant can
   865  		// put the offset in the addressing.
   866  		// Could do the same for slice except that we need
   867  		// to use the real index for the bounds checking.
   868  		if(isfixedarray(n->left->type) ||
   869  		   (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
   870  		if(isconst(n->right, CTINT)) {
   871  			// Compute &a.
   872  			if(!isptr[n->left->type->etype])
   873  				igen(n->left, a, res);
   874  			else {
   875  				igen(n->left, &n1, res);
   876  				cgen_checknil(&n1);
   877  				regalloc(a, types[tptr], res);
   878  				gmove(&n1, a);
   879  				regfree(&n1);
   880  				a->op = OINDREG;
   881  			}
   882  
   883  			// Compute &a[i] as &a + i*width.
   884  			a->type = n->type;
   885  			a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
   886  			return;
   887  		}
   888  		break;
   889  	}
   890  
   891  	// release register for now, to avoid
   892  	// confusing tempname.
   893  	if(res != N && res->op == OREGISTER)
   894  		reg[res->val.u.reg]--;
   895  	tempname(&n1, types[tptr]);
   896  	agen(n, &n1);
   897  	if(res != N && res->op == OREGISTER)
   898  		reg[res->val.u.reg]++;
   899  	regalloc(a, types[tptr], res);
   900  	gmove(&n1, a);
   901  	a->op = OINDREG;
   902  	a->type = n->type;
   903  }
   904  
   905  /*
   906   * branch gen
   907   *	if(n == true) goto to;
   908   */
   909  void
   910  bgen(Node *n, int true, int likely, Prog *to)
   911  {
   912  	int et, a;
   913  	Node *nl, *nr, *r;
   914  	Node n1, n2, tmp;
   915  	Prog *p1, *p2;
   916  
   917  	if(debug['g']) {
   918  		dump("\nbgen", n);
   919  	}
   920  
   921  	if(n == N)
   922  		n = nodbool(1);
   923  
   924  	if(n->ninit != nil)
   925  		genlist(n->ninit);
   926  
   927  	if(n->type == T) {
   928  		convlit(&n, types[TBOOL]);
   929  		if(n->type == T)
   930  			return;
   931  	}
   932  
   933  	et = n->type->etype;
   934  	if(et != TBOOL) {
   935  		yyerror("cgen: bad type %T for %O", n->type, n->op);
   936  		patch(gins(AEND, N, N), to);
   937  		return;
   938  	}
   939  
   940  	while(n->op == OCONVNOP) {
   941  		n = n->left;
   942  		if(n->ninit != nil)
   943  			genlist(n->ninit);
   944  	}
   945  
   946  	nl = n->left;
   947  	nr = N;
   948  
   949  	if(nl != N && isfloat[nl->type->etype]) {
   950  		bgen_float(n, true, likely, to);
   951  		return;
   952  	}
   953  
   954  	switch(n->op) {
   955  	default:
   956  	def:
   957  		regalloc(&n1, n->type, N);
   958  		cgen(n, &n1);
   959  		nodconst(&n2, n->type, 0);
   960  		gins(optoas(OCMP, n->type), &n1, &n2);
   961  		a = AJNE;
   962  		if(!true)
   963  			a = AJEQ;
   964  		patch(gbranch(a, n->type, likely), to);
   965  		regfree(&n1);
   966  		return;
   967  
   968  	case OLITERAL:
   969  		// need to ask if it is bool?
   970  		if(!true == !n->val.u.bval)
   971  			patch(gbranch(AJMP, T, 0), to);
   972  		return;
   973  
   974  	case ONAME:
   975  		if(!n->addable)
   976  			goto def;
   977  		nodconst(&n1, n->type, 0);
   978  		gins(optoas(OCMP, n->type), n, &n1);
   979  		a = AJNE;
   980  		if(!true)
   981  			a = AJEQ;
   982  		patch(gbranch(a, n->type, likely), to);
   983  		return;
   984  
   985  	case OANDAND:
   986  		if(!true)
   987  			goto caseor;
   988  
   989  	caseand:
   990  		p1 = gbranch(AJMP, T, 0);
   991  		p2 = gbranch(AJMP, T, 0);
   992  		patch(p1, pc);
   993  		bgen(n->left, !true, -likely, p2);
   994  		bgen(n->right, !true, -likely, p2);
   995  		p1 = gbranch(AJMP, T, 0);
   996  		patch(p1, to);
   997  		patch(p2, pc);
   998  		return;
   999  
  1000  	case OOROR:
  1001  		if(!true)
  1002  			goto caseand;
  1003  
  1004  	caseor:
  1005  		bgen(n->left, true, likely, to);
  1006  		bgen(n->right, true, likely, to);
  1007  		return;
  1008  
  1009  	case OEQ:
  1010  	case ONE:
  1011  	case OLT:
  1012  	case OGT:
  1013  	case OLE:
  1014  	case OGE:
  1015  		nr = n->right;
  1016  		if(nr == N || nr->type == T)
  1017  			return;
  1018  
  1019  	case ONOT:	// unary
  1020  		nl = n->left;
  1021  		if(nl == N || nl->type == T)
  1022  			return;
  1023  	}
  1024  
  1025  	switch(n->op) {
  1026  	case ONOT:
  1027  		bgen(nl, !true, likely, to);
  1028  		break;
  1029  
  1030  	case OEQ:
  1031  	case ONE:
  1032  	case OLT:
  1033  	case OGT:
  1034  	case OLE:
  1035  	case OGE:
  1036  		a = n->op;
  1037  		if(!true) {
  1038  			a = brcom(a);
  1039  			true = !true;
  1040  		}
  1041  
  1042  		// make simplest on right
  1043  		if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
  1044  			a = brrev(a);
  1045  			r = nl;
  1046  			nl = nr;
  1047  			nr = r;
  1048  		}
  1049  
  1050  		if(isslice(nl->type)) {
  1051  			// front end should only leave cmp to literal nil
  1052  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
  1053  				yyerror("illegal slice comparison");
  1054  				break;
  1055  			}
  1056  			a = optoas(a, types[tptr]);
  1057  			igen(nl, &n1, N);
  1058  			n1.xoffset += Array_array;
  1059  			n1.type = types[tptr];
  1060  			nodconst(&tmp, types[tptr], 0);
  1061  			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
  1062  			patch(gbranch(a, types[tptr], likely), to);
  1063  			regfree(&n1);
  1064  			break;
  1065  		}
  1066  
  1067  		if(isinter(nl->type)) {
  1068  			// front end should only leave cmp to literal nil
  1069  			if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
  1070  				yyerror("illegal interface comparison");
  1071  				break;
  1072  			}
  1073  			a = optoas(a, types[tptr]);
  1074  			igen(nl, &n1, N);
  1075  			n1.type = types[tptr];
  1076  			nodconst(&tmp, types[tptr], 0);
  1077  			gins(optoas(OCMP, types[tptr]), &n1, &tmp);
  1078  			patch(gbranch(a, types[tptr], likely), to);
  1079  			regfree(&n1);
  1080  			break;
  1081  		}
  1082  
  1083  		if(iscomplex[nl->type->etype]) {
  1084  			complexbool(a, nl, nr, true, likely, to);
  1085  			break;
  1086  		}
  1087  
  1088  		if(is64(nr->type)) {
  1089  			if(!nl->addable || isconst(nl, CTINT)) {
  1090  				tempname(&n1, nl->type);
  1091  				cgen(nl, &n1);
  1092  				nl = &n1;
  1093  			}
  1094  			if(!nr->addable) {
  1095  				tempname(&n2, nr->type);
  1096  				cgen(nr, &n2);
  1097  				nr = &n2;
  1098  			}
  1099  			cmp64(nl, nr, a, likely, to);
  1100  			break;
  1101  		}
  1102  
  1103  		if(nr->ullman >= UINF) {
  1104  			if(!nl->addable) {
  1105  				tempname(&n1, nl->type);
  1106  				cgen(nl, &n1);
  1107  				nl = &n1;
  1108  			}
  1109  			if(!nr->addable) {
  1110  				tempname(&tmp, nr->type);
  1111  				cgen(nr, &tmp);
  1112  				nr = &tmp;
  1113  			}
  1114  			regalloc(&n2, nr->type, N);
  1115  			cgen(nr, &n2);
  1116  			nr = &n2;
  1117  			goto cmp;
  1118  		}
  1119  
  1120  		if(!nl->addable) {
  1121  			tempname(&n1, nl->type);
  1122  			cgen(nl, &n1);
  1123  			nl = &n1;
  1124  		}
  1125  
  1126  		if(smallintconst(nr)) {
  1127  			gins(optoas(OCMP, nr->type), nl, nr);
  1128  			patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
  1129  			break;
  1130  		}
  1131  
  1132  		if(!nr->addable) {
  1133  			tempname(&tmp, nr->type);
  1134  			cgen(nr, &tmp);
  1135  			nr = &tmp;
  1136  		}
  1137  		regalloc(&n2, nr->type, N);
  1138  		gmove(nr, &n2);
  1139  		nr = &n2;
  1140  
  1141  cmp:
  1142  		gins(optoas(OCMP, nr->type), nl, nr);
  1143  		patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
  1144  
  1145  		if(nl->op == OREGISTER)
  1146  			regfree(nl);
  1147  		regfree(nr);
  1148  		break;
  1149  	}
  1150  }
  1151  
  1152  /*
  1153   * n is on stack, either local variable
  1154   * or return value from function call.
  1155   * return n's offset from SP.
  1156   */
  1157  int32
  1158  stkof(Node *n)
  1159  {
  1160  	Type *t;
  1161  	Iter flist;
  1162  	int32 off;
  1163  
  1164  	switch(n->op) {
  1165  	case OINDREG:
  1166  		return n->xoffset;
  1167  
  1168  	case ODOT:
  1169  		t = n->left->type;
  1170  		if(isptr[t->etype])
  1171  			break;
  1172  		off = stkof(n->left);
  1173  		if(off == -1000 || off == 1000)
  1174  			return off;
  1175  		return off + n->xoffset;
  1176  
  1177  	case OINDEX:
  1178  		t = n->left->type;
  1179  		if(!isfixedarray(t))
  1180  			break;
  1181  		off = stkof(n->left);
  1182  		if(off == -1000 || off == 1000)
  1183  			return off;
  1184  		if(isconst(n->right, CTINT))
  1185  			return off + t->type->width * mpgetfix(n->right->val.u.xval);
  1186  		return 1000;
  1187  		
  1188  	case OCALLMETH:
  1189  	case OCALLINTER:
  1190  	case OCALLFUNC:
  1191  		t = n->left->type;
  1192  		if(isptr[t->etype])
  1193  			t = t->type;
  1194  
  1195  		t = structfirst(&flist, getoutarg(t));
  1196  		if(t != T)
  1197  			return t->width;
  1198  		break;
  1199  	}
  1200  
  1201  	// botch - probably failing to recognize address
  1202  	// arithmetic on the above. eg INDEX and DOT
  1203  	return -1000;
  1204  }
  1205  
  1206  /*
  1207   * struct gen
  1208   *	memmove(&res, &n, w);
  1209   */
  1210  void
  1211  sgen(Node *n, Node *res, int64 w)
  1212  {
  1213  	Node dst, src, tdst, tsrc;
  1214  	int32 c, q, odst, osrc;
  1215  	NodeList *l;
  1216  	Prog *p;
  1217  
  1218  	if(debug['g']) {
  1219  		print("\nsgen w=%lld\n", w);
  1220  		dump("r", n);
  1221  		dump("res", res);
  1222  	}
  1223  	if(n->ullman >= UINF && res->ullman >= UINF)
  1224  		fatal("sgen UINF");
  1225  
  1226  	if(w < 0 || (int32)w != w)
  1227  		fatal("sgen copy %lld", w);
  1228  
  1229  	if(w == 0) {
  1230  		// evaluate side effects only.
  1231  		tempname(&tdst, types[tptr]);
  1232  		agen(res, &tdst);
  1233  		agen(n, &tdst);
  1234  		return;
  1235  	}
  1236  
  1237  	// If copying .args, that's all the results, so record definition sites
  1238  	// for them for the liveness analysis.
  1239  	if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
  1240  		for(l = curfn->dcl; l != nil; l = l->next)
  1241  			if(l->n->class == PPARAMOUT)
  1242  				gvardef(l->n);
  1243  
  1244  	// Avoid taking the address for simple enough types.
  1245  	if(componentgen(n, res))
  1246  		return;
  1247  
  1248  	// offset on the stack
  1249  	osrc = stkof(n);
  1250  	odst = stkof(res);
  1251  	
  1252  	if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
  1253  		// osrc and odst both on stack, and at least one is in
  1254  		// an unknown position.  Could generate code to test
  1255  		// for forward/backward copy, but instead just copy
  1256  		// to a temporary location first.
  1257  		tempname(&tsrc, n->type);
  1258  		sgen(n, &tsrc, w);
  1259  		sgen(&tsrc, res, w);
  1260  		return;
  1261  	}
  1262  
  1263  	nodreg(&dst, types[tptr], D_DI);
  1264  	nodreg(&src, types[tptr], D_SI);
  1265  
  1266  	tempname(&tsrc, types[tptr]);
  1267  	tempname(&tdst, types[tptr]);
  1268  	if(!n->addable)
  1269  		agen(n, &tsrc);
  1270  	if(!res->addable)
  1271  		agen(res, &tdst);
  1272  	if(n->addable)
  1273  		agen(n, &src);
  1274  	else
  1275  		gmove(&tsrc, &src);
  1276  
  1277  	if(res->op == ONAME)
  1278  		gvardef(res);
  1279  
  1280  	if(res->addable)
  1281  		agen(res, &dst);
  1282  	else
  1283  		gmove(&tdst, &dst);
  1284  
  1285  	c = w % 4;	// bytes
  1286  	q = w / 4;	// doublewords
  1287  
  1288  	// if we are copying forward on the stack and
  1289  	// the src and dst overlap, then reverse direction
  1290  	if(osrc < odst && odst < osrc+w) {
  1291  		// reverse direction
  1292  		gins(ASTD, N, N);		// set direction flag
  1293  		if(c > 0) {
  1294  			gconreg(AADDL, w-1, D_SI);
  1295  			gconreg(AADDL, w-1, D_DI);
  1296  
  1297  			gconreg(AMOVL, c, D_CX);
  1298  			gins(AREP, N, N);	// repeat
  1299  			gins(AMOVSB, N, N);	// MOVB *(SI)-,*(DI)-
  1300  		}
  1301  
  1302  		if(q > 0) {
  1303  			if(c > 0) {
  1304  				gconreg(AADDL, -3, D_SI);
  1305  				gconreg(AADDL, -3, D_DI);
  1306  			} else {
  1307  				gconreg(AADDL, w-4, D_SI);
  1308  				gconreg(AADDL, w-4, D_DI);
  1309  			}
  1310  			gconreg(AMOVL, q, D_CX);
  1311  			gins(AREP, N, N);	// repeat
  1312  			gins(AMOVSL, N, N);	// MOVL *(SI)-,*(DI)-
  1313  		}
  1314  		// we leave with the flag clear
  1315  		gins(ACLD, N, N);
  1316  	} else {
  1317  		gins(ACLD, N, N);	// paranoia.  TODO(rsc): remove?
  1318  		// normal direction
  1319  		if(q > 128 || (q >= 4 && nacl)) {
  1320  			gconreg(AMOVL, q, D_CX);
  1321  			gins(AREP, N, N);	// repeat
  1322  			gins(AMOVSL, N, N);	// MOVL *(SI)+,*(DI)+
  1323  		} else if(q >= 4) {
  1324  			p = gins(ADUFFCOPY, N, N);
  1325  			p->to.type = D_ADDR;
  1326  			p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
  1327  			// 10 and 128 = magic constants: see ../../pkg/runtime/asm_386.s
  1328  			p->to.offset = 10*(128-q);
  1329  		} else
  1330  		while(q > 0) {
  1331  			gins(AMOVSL, N, N);	// MOVL *(SI)+,*(DI)+
  1332  			q--;
  1333  		}
  1334  		while(c > 0) {
  1335  			gins(AMOVSB, N, N);	// MOVB *(SI)+,*(DI)+
  1336  			c--;
  1337  		}
  1338  	}
  1339  }
  1340  
  1341  static int
  1342  cadable(Node *n)
  1343  {
  1344  	if(!n->addable) {
  1345  		// dont know how it happens,
  1346  		// but it does
  1347  		return 0;
  1348  	}
  1349  
  1350  	switch(n->op) {
  1351  	case ONAME:
  1352  		return 1;
  1353  	}
  1354  	return 0;
  1355  }
  1356  
  1357  /*
  1358   * copy a composite value by moving its individual components.
  1359   * Slices, strings and interfaces are supported.
  1360   * nr is N when assigning a zero value.
  1361   * return 1 if can do, 0 if can't.
  1362   */
  1363  int
  1364  componentgen(Node *nr, Node *nl)
  1365  {
  1366  	Node nodl, nodr;
  1367  	int freel, freer;
  1368  
  1369  	freel = 0;
  1370  	freer = 0;
  1371  
  1372  	switch(nl->type->etype) {
  1373  	default:
  1374  		goto no;
  1375  
  1376  	case TARRAY:
  1377  		if(!isslice(nl->type))
  1378  			goto no;
  1379  	case TSTRING:
  1380  	case TINTER:
  1381  		break;
  1382  	}
  1383  
  1384  	nodl = *nl;
  1385  	if(!cadable(nl)) {
  1386  		if(nr == N || !cadable(nr))
  1387  			goto no;
  1388  		igen(nl, &nodl, N);
  1389  		freel = 1;
  1390  	}
  1391  
  1392  	if(nr != N) {
  1393  		nodr = *nr;
  1394  		if(!cadable(nr)) {
  1395  			igen(nr, &nodr, N);
  1396  			freer = 1;
  1397  		}
  1398  	}
  1399  
  1400  	// nl and nr are 'cadable' which basically means they are names (variables) now.
  1401  	// If they are the same variable, don't generate any code, because the
  1402  	// VARDEF we generate will mark the old value as dead incorrectly.
  1403  	// (And also the assignments are useless.)
  1404  	if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
  1405  		goto yes;
  1406  
  1407  	switch(nl->type->etype) {
  1408  	case TARRAY:
  1409  		if(nl->op == ONAME)
  1410  			gvardef(nl);
  1411  		nodl.xoffset += Array_array;
  1412  		nodl.type = ptrto(nl->type->type);
  1413  
  1414  		if(nr != N) {
  1415  			nodr.xoffset += Array_array;
  1416  			nodr.type = nodl.type;
  1417  		} else
  1418  			nodconst(&nodr, nodl.type, 0);
  1419  		gmove(&nodr, &nodl);
  1420  
  1421  		nodl.xoffset += Array_nel-Array_array;
  1422  		nodl.type = types[TUINT32];
  1423  
  1424  		if(nr != N) {
  1425  			nodr.xoffset += Array_nel-Array_array;
  1426  			nodr.type = nodl.type;
  1427  		} else
  1428  			nodconst(&nodr, nodl.type, 0);
  1429  		gmove(&nodr, &nodl);
  1430  
  1431  		nodl.xoffset += Array_cap-Array_nel;
  1432  		nodl.type = types[TUINT32];
  1433  
  1434  		if(nr != N) {
  1435  			nodr.xoffset += Array_cap-Array_nel;
  1436  			nodr.type = nodl.type;
  1437  		} else
  1438  			nodconst(&nodr, nodl.type, 0);
  1439  		gmove(&nodr, &nodl);
  1440  
  1441  		goto yes;
  1442  
  1443  	case TSTRING:
  1444  		if(nl->op == ONAME)
  1445  			gvardef(nl);
  1446  		nodl.xoffset += Array_array;
  1447  		nodl.type = ptrto(types[TUINT8]);
  1448  
  1449  		if(nr != N) {
  1450  			nodr.xoffset += Array_array;
  1451  			nodr.type = nodl.type;
  1452  		} else
  1453  			nodconst(&nodr, nodl.type, 0);
  1454  		gmove(&nodr, &nodl);
  1455  
  1456  		nodl.xoffset += Array_nel-Array_array;
  1457  		nodl.type = types[TUINT32];
  1458  
  1459  		if(nr != N) {
  1460  			nodr.xoffset += Array_nel-Array_array;
  1461  			nodr.type = nodl.type;
  1462  		} else
  1463  			nodconst(&nodr, nodl.type, 0);
  1464  		gmove(&nodr, &nodl);
  1465  
  1466  		goto yes;
  1467  
  1468  	case TINTER:
  1469  		if(nl->op == ONAME)
  1470  			gvardef(nl);
  1471  		nodl.xoffset += Array_array;
  1472  		nodl.type = ptrto(types[TUINT8]);
  1473  
  1474  		if(nr != N) {
  1475  			nodr.xoffset += Array_array;
  1476  			nodr.type = nodl.type;
  1477  		} else
  1478  			nodconst(&nodr, nodl.type, 0);
  1479  		gmove(&nodr, &nodl);
  1480  
  1481  		nodl.xoffset += Array_nel-Array_array;
  1482  		nodl.type = ptrto(types[TUINT8]);
  1483  
  1484  		if(nr != N) {
  1485  			nodr.xoffset += Array_nel-Array_array;
  1486  			nodr.type = nodl.type;
  1487  		} else
  1488  			nodconst(&nodr, nodl.type, 0);
  1489  		gmove(&nodr, &nodl);
  1490  
  1491  		goto yes;
  1492  	}
  1493  
  1494  no:
  1495  	if(freer)
  1496  		regfree(&nodr);
  1497  	if(freel)
  1498  		regfree(&nodl);
  1499  	return 0;
  1500  
  1501  yes:
  1502  	if(freer)
  1503  		regfree(&nodr);
  1504  	if(freel)
  1505  		regfree(&nodl);
  1506  	return 1;
  1507  }