The Go Programming Language

Text file src/cmd/gc/sinit.c

     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	/*
     6	 * static initialization
     7	 */
     8	
     9	#include	"go.h"
    10	
    11	static NodeList *initlist;
    12	static void init2(Node*, NodeList**);
    13	static void init2list(NodeList*, NodeList**);
    14	
    15	static void
    16	init1(Node *n, NodeList **out)
    17	{
    18		NodeList *l;
    19	
    20		if(n == N)
    21			return;
    22		init1(n->left, out);
    23		init1(n->right, out);
    24		for(l=n->list; l; l=l->next)
    25			init1(l->n, out);
    26	
    27		if(n->op != ONAME)
    28			return;
    29		switch(n->class) {
    30		case PEXTERN:
    31		case PFUNC:
    32			break;
    33		default:
    34			if(isblank(n) && n->defn != N && !n->defn->initorder) {
    35				n->defn->initorder = 1;
    36				*out = list(*out, n->defn);
    37			}
    38			return;
    39		}
    40	
    41		if(n->initorder == 1)
    42			return;
    43		if(n->initorder == 2) {
    44			if(n->class == PFUNC)
    45				return;
    46			
    47			// if there have already been errors printed,
    48			// those errors probably confused us and
    49			// there might not be a loop.  let the user
    50			// fix those first.
    51			flusherrors();
    52			if(nerrors > 0)
    53				errorexit();
    54	
    55			print("initialization loop:\n");
    56			for(l=initlist;; l=l->next) {
    57				if(l->next == nil)
    58					break;
    59				l->next->end = l;
    60			}
    61			for(; l; l=l->end)
    62				print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
    63			print("\t%L %S\n", n->lineno, n->sym);
    64			errorexit();
    65		}
    66		n->initorder = 2;
    67		l = malloc(sizeof *l);
    68		l->next = initlist;
    69		l->n = n;
    70		l->end = nil;
    71		initlist = l;
    72	
    73		// make sure that everything n depends on is initialized.
    74		// n->defn is an assignment to n
    75		if(n->defn != N) {
    76			switch(n->defn->op) {
    77			default:
    78				goto bad;
    79	
    80			case ODCLFUNC:
    81				init2list(n->defn->nbody, out);
    82				break;
    83	
    84			case OAS:
    85				if(n->defn->left != n)
    86					goto bad;
    87				n->defn->dodata = 1;
    88				init1(n->defn->right, out);
    89				if(debug['j'])
    90					print("%S\n", n->sym);
    91				*out = list(*out, n->defn);
    92				break;
    93			
    94			case OAS2FUNC:
    95			case OAS2MAPR:
    96			case OAS2DOTTYPE:
    97			case OAS2RECV:
    98				if(n->defn->initorder)
    99					break;
   100				n->defn->initorder = 1;
   101				for(l=n->defn->rlist; l; l=l->next)
   102					init1(l->n, out);
   103				*out = list(*out, n->defn);
   104				break;
   105			}
   106		}
   107		l = initlist;
   108		initlist = l->next;
   109		if(l->n != n)
   110			fatal("bad initlist");
   111		free(l);
   112		n->initorder = 1;
   113		return;
   114	
   115	bad:
   116		dump("defn", n->defn);
   117		fatal("init1: bad defn");
   118	}
   119	
   120	// recurse over n, doing init1 everywhere.
   121	static void
   122	init2(Node *n, NodeList **out)
   123	{
   124		if(n == N || n->initorder == 1)
   125			return;
   126		init1(n, out);
   127		init2(n->left, out);
   128		init2(n->right, out);
   129		init2(n->ntest, out);
   130		init2list(n->ninit, out);
   131		init2list(n->list, out);
   132		init2list(n->rlist, out);
   133		init2list(n->nbody, out);
   134		init2list(n->nelse, out);
   135	}
   136	
   137	static void
   138	init2list(NodeList *l, NodeList **out)
   139	{
   140		for(; l; l=l->next)
   141			init2(l->n, out);
   142	}
   143	
   144	
   145	static void
   146	initreorder(NodeList *l, NodeList **out)
   147	{
   148		Node *n;
   149	
   150		for(; l; l=l->next) {
   151			n = l->n;
   152			switch(n->op) {
   153			case ODCLFUNC:
   154			case ODCLCONST:
   155			case ODCLTYPE:
   156				continue;
   157			}
   158			initreorder(n->ninit, out);
   159			n->ninit = nil;
   160			init1(n, out);
   161		}
   162	}
   163	
   164	NodeList*
   165	initfix(NodeList *l)
   166	{
   167		NodeList *lout;
   168	
   169		lout = nil;
   170		initreorder(l, &lout);
   171		return lout;
   172	}
   173	
   174	/*
   175	 * from here down is the walk analysis
   176	 * of composite literals.
   177	 * most of the work is to generate
   178	 * data statements for the constant
   179	 * part of the composite literal.
   180	 */
   181	
   182	static	void	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   183	static	void	arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
   184	static	void	slicelit(int ctxt, Node *n, Node *var, NodeList **init);
   185	static	void	maplit(int ctxt, Node *n, Node *var, NodeList **init);
   186	
   187	static Node*
   188	staticname(Type *t, int ctxt)
   189	{
   190		Node *n;
   191	
   192		snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen);
   193		statuniqgen++;
   194		n = newname(lookup(namebuf));
   195		if(!ctxt)
   196			n->readonly = 1;
   197		addvar(n, t, PEXTERN);
   198		return n;
   199	}
   200	
   201	static int
   202	isliteral(Node *n)
   203	{
   204		if(n->op == OLITERAL)
   205			if(n->val.ctype != CTNIL)
   206				return 1;
   207		return 0;
   208	}
   209	
   210	static int
   211	simplename(Node *n)
   212	{
   213		if(n->op != ONAME)
   214			goto no;
   215		if(!n->addable)
   216			goto no;
   217		if(n->class & PHEAP)
   218			goto no;
   219		if(n->class == PPARAMREF)
   220			goto no;
   221		return 1;
   222	
   223	no:
   224		return 0;
   225	}
   226	
   227	static void
   228	litas(Node *l, Node *r, NodeList **init)
   229	{
   230		Node *a;
   231	
   232		a = nod(OAS, l, r);
   233		typecheck(&a, Etop);
   234		walkexpr(&a, init);
   235		*init = list(*init, a);
   236	}
   237	
   238	enum
   239	{
   240		MODEDYNAM	= 1,
   241		MODECONST	= 2,
   242	};
   243	
   244	static int
   245	getdyn(Node *n, int top)
   246	{
   247		NodeList *nl;
   248		Node *value;
   249		int mode;
   250	
   251		mode = 0;
   252		switch(n->op) {
   253		default:
   254			if(isliteral(n))
   255				return MODECONST;
   256			return MODEDYNAM;
   257		case OARRAYLIT:
   258			if(!top && n->type->bound < 0)
   259				return MODEDYNAM;
   260		case OSTRUCTLIT:
   261			break;
   262		}
   263	
   264		for(nl=n->list; nl; nl=nl->next) {
   265			value = nl->n->right;
   266			mode |= getdyn(value, 0);
   267			if(mode == (MODEDYNAM|MODECONST))
   268				break;
   269		}
   270		return mode;
   271	}
   272	
   273	static void
   274	structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   275	{
   276		Node *r, *a;
   277		NodeList *nl;
   278		Node *index, *value;
   279	
   280		for(nl=n->list; nl; nl=nl->next) {
   281			r = nl->n;
   282			if(r->op != OKEY)
   283				fatal("structlit: rhs not OKEY: %N", r);
   284			index = r->left;
   285			value = r->right;
   286	
   287			switch(value->op) {
   288			case OARRAYLIT:
   289				if(value->type->bound < 0) {
   290					if(pass == 1 && ctxt != 0) {
   291						a = nod(ODOT, var, newname(index->sym));
   292						slicelit(ctxt, value, a, init);
   293					} else
   294					if(pass == 2 && ctxt == 0) {
   295						a = nod(ODOT, var, newname(index->sym));
   296						slicelit(ctxt, value, a, init);
   297					} else
   298					if(pass == 3)
   299						break;
   300					continue;
   301				}
   302				a = nod(ODOT, var, newname(index->sym));
   303				arraylit(ctxt, pass, value, a, init);
   304				continue;
   305	
   306			case OSTRUCTLIT:
   307				a = nod(ODOT, var, newname(index->sym));
   308				structlit(ctxt, pass, value, a, init);
   309				continue;
   310			}
   311	
   312			if(isliteral(value)) {
   313				if(pass == 2)
   314					continue;
   315			} else
   316				if(pass == 1)
   317					continue;
   318	
   319			// build list of var.field = expr
   320			a = nod(ODOT, var, newname(index->sym));
   321			a = nod(OAS, a, value);
   322			typecheck(&a, Etop);
   323			walkexpr(&a, init);
   324			if(pass == 1) {
   325				if(a->op != OAS)
   326					fatal("structlit: not as");
   327				a->dodata = 2;
   328			}
   329			*init = list(*init, a);
   330		}
   331	}
   332	
   333	static void
   334	arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
   335	{
   336		Node *r, *a;
   337		NodeList *l;
   338		Node *index, *value;
   339	
   340		for(l=n->list; l; l=l->next) {
   341			r = l->n;
   342			if(r->op != OKEY)
   343				fatal("arraylit: rhs not OKEY: %N", r);
   344			index = r->left;
   345			value = r->right;
   346	
   347			switch(value->op) {
   348			case OARRAYLIT:
   349				if(value->type->bound < 0) {
   350					if(pass == 1 && ctxt != 0) {
   351						a = nod(OINDEX, var, index);
   352						slicelit(ctxt, value, a, init);
   353					} else
   354					if(pass == 2 && ctxt == 0) {
   355						a = nod(OINDEX, var, index);
   356						slicelit(ctxt, value, a, init);
   357					} else
   358					if(pass == 3)
   359						break;
   360					continue;
   361				}
   362				a = nod(OINDEX, var, index);
   363				arraylit(ctxt, pass, value, a, init);
   364				continue;
   365	
   366			case OSTRUCTLIT:
   367				a = nod(OINDEX, var, index);
   368				structlit(ctxt, pass, value, a, init);
   369				continue;
   370			}
   371	
   372			if(isliteral(index) && isliteral(value)) {
   373				if(pass == 2)
   374					continue;
   375			} else
   376				if(pass == 1)
   377					continue;
   378	
   379			// build list of var[index] = value
   380			a = nod(OINDEX, var, index);
   381			a = nod(OAS, a, value);
   382			typecheck(&a, Etop);
   383			walkexpr(&a, init);	// add any assignments in r to top
   384			if(pass == 1) {
   385				if(a->op != OAS)
   386					fatal("structlit: not as");
   387				a->dodata = 2;
   388			}
   389			*init = list(*init, a);
   390		}
   391	}
   392	
   393	static void
   394	slicelit(int ctxt, Node *n, Node *var, NodeList **init)
   395	{
   396		Node *r, *a;
   397		NodeList *l;
   398		Type *t;
   399		Node *vstat, *vauto;
   400		Node *index, *value;
   401		int mode;
   402	
   403		// make an array type
   404		t = shallow(n->type);
   405		t->bound = mpgetfix(n->right->val.u.xval);
   406		t->width = 0;
   407		t->sym = nil;
   408		dowidth(t);
   409	
   410		if(ctxt != 0) {
   411	
   412			// put everything into static array
   413			vstat = staticname(t, ctxt);
   414			arraylit(ctxt, 1, n, vstat, init);
   415			arraylit(ctxt, 2, n, vstat, init);
   416	
   417			// copy static to slice
   418			a = nod(OSLICE, vstat, nod(OKEY, N, N));
   419			a = nod(OAS, var, a);
   420			typecheck(&a, Etop);
   421			a->dodata = 2;
   422			*init = list(*init, a);
   423			return;
   424		}
   425	
   426		// recipe for var = []t{...}
   427		// 1. make a static array
   428		//	var vstat [...]t
   429		// 2. assign (data statements) the constant part
   430		//	vstat = constpart{}
   431		// 3. make an auto pointer to array and allocate heap to it
   432		//	var vauto *[...]t = new([...]t)
   433		// 4. copy the static array to the auto array
   434		//	*vauto = vstat
   435		// 5. assign slice of allocated heap to var
   436		//	var = [0:]*auto
   437		// 6. for each dynamic part assign to the slice
   438		//	var[i] = dynamic part
   439		//
   440		// an optimization is done if there is no constant part
   441		//	3. var vauto *[...]t = new([...]t)
   442		//	5. var = [0:]*auto
   443		//	6. var[i] = dynamic part
   444	
   445		// if the literal contains constants,
   446		// make static initialized array (1),(2)
   447		vstat = N;
   448		mode = getdyn(n, 1);
   449		if(mode & MODECONST) {
   450			vstat = staticname(t, ctxt);
   451			arraylit(ctxt, 1, n, vstat, init);
   452		}
   453	
   454		// make new auto *array (3 declare)
   455		vauto = nod(OXXX, N, N);
   456		tempname(vauto, ptrto(t));
   457	
   458		// set auto to point at new heap (3 assign)
   459		a = nod(ONEW, N, N);
   460		a->list = list1(typenod(t));
   461		a = nod(OAS, vauto, a);
   462		typecheck(&a, Etop);
   463		walkexpr(&a, init);
   464		*init = list(*init, a);
   465	
   466		if(vstat != N) {
   467			// copy static to heap (4)
   468			a = nod(OIND, vauto, N);
   469			a = nod(OAS, a, vstat);
   470			typecheck(&a, Etop);
   471			walkexpr(&a, init);
   472			*init = list(*init, a);
   473		}
   474	
   475		// make slice out of heap (5)
   476		a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
   477		typecheck(&a, Etop);
   478		walkexpr(&a, init);
   479		*init = list(*init, a);
   480	
   481		// put dynamics into slice (6)
   482		for(l=n->list; l; l=l->next) {
   483			r = l->n;
   484			if(r->op != OKEY)
   485				fatal("slicelit: rhs not OKEY: %N", r);
   486			index = r->left;
   487			value = r->right;
   488			a = nod(OINDEX, var, index);
   489			a->etype = 1;	// no bounds checking
   490			// TODO need to check bounds?
   491	
   492			switch(value->op) {
   493			case OARRAYLIT:
   494				if(value->type->bound < 0)
   495					break;
   496				arraylit(ctxt, 2, value, a, init);
   497				continue;
   498	
   499			case OSTRUCTLIT:
   500				structlit(ctxt, 2, value, a, init);
   501				continue;
   502			}
   503	
   504			if(isliteral(index) && isliteral(value))
   505				continue;
   506	
   507			// build list of var[c] = expr
   508			a = nod(OAS, a, value);
   509			typecheck(&a, Etop);
   510			walkexpr(&a, init);
   511			*init = list(*init, a);
   512		}
   513	}
   514	
   515	static void
   516	maplit(int ctxt, Node *n, Node *var, NodeList **init)
   517	{
   518		Node *r, *a;
   519		NodeList *l;
   520		int nerr, b;
   521		Type *t, *tk, *tv, *t1;
   522		Node *vstat, *index, *value;
   523		Sym *syma, *symb;
   524	
   525	ctxt = 0;
   526	
   527		// make the map var
   528		nerr = nerrors;
   529	
   530		a = nod(OMAKE, N, N);
   531		a->list = list1(typenod(n->type));
   532		litas(var, a, init);
   533	
   534		// count the initializers
   535		b = 0;
   536		for(l=n->list; l; l=l->next) {
   537			r = l->n;
   538	
   539			if(r->op != OKEY)
   540				fatal("slicelit: rhs not OKEY: %N", r);
   541			index = r->left;
   542			value = r->right;
   543	
   544			if(isliteral(index) && isliteral(value))
   545				b++;
   546		}
   547	
   548		t = T;
   549		if(b != 0) {
   550			// build type [count]struct { a Tindex, b Tvalue }
   551			t = n->type;
   552			tk = t->down;
   553			tv = t->type;
   554	
   555			symb = lookup("b");
   556			t = typ(TFIELD);
   557			t->type = tv;
   558			t->sym = symb;
   559	
   560			syma = lookup("a");
   561			t1 = t;
   562			t = typ(TFIELD);
   563			t->type = tk;
   564			t->sym = syma;
   565			t->down = t1;
   566	
   567			t1 = t;
   568			t = typ(TSTRUCT);
   569			t->type = t1;
   570	
   571			t1 = t;
   572			t = typ(TARRAY);
   573			t->bound = b;
   574			t->type = t1;
   575	
   576			dowidth(t);
   577	
   578			// make and initialize static array
   579			vstat = staticname(t, ctxt);
   580			b = 0;
   581			for(l=n->list; l; l=l->next) {
   582				r = l->n;
   583	
   584				if(r->op != OKEY)
   585					fatal("slicelit: rhs not OKEY: %N", r);
   586				index = r->left;
   587				value = r->right;
   588	
   589				if(isliteral(index) && isliteral(value)) {
   590					// build vstat[b].a = key;
   591					a = nodintconst(b);
   592					a = nod(OINDEX, vstat, a);
   593					a = nod(ODOT, a, newname(syma));
   594					a = nod(OAS, a, index);
   595					typecheck(&a, Etop);
   596					walkexpr(&a, init);
   597					a->dodata = 2;
   598					*init = list(*init, a);
   599	
   600					// build vstat[b].b = value;
   601					a = nodintconst(b);
   602					a = nod(OINDEX, vstat, a);
   603					a = nod(ODOT, a, newname(symb));
   604					a = nod(OAS, a, value);
   605					typecheck(&a, Etop);
   606					walkexpr(&a, init);
   607					a->dodata = 2;
   608					*init = list(*init, a);
   609	
   610					b++;
   611				}
   612			}
   613	
   614			// loop adding structure elements to map
   615			// for i = 0; i < len(vstat); i++ {
   616			//	map[vstat[i].a] = vstat[i].b
   617			// }
   618			index = nod(OXXX, N, N);
   619			tempname(index, types[TINT]);
   620	
   621			a = nod(OINDEX, vstat, index);
   622			a->etype = 1;	// no bounds checking
   623			a = nod(ODOT, a, newname(symb));
   624	
   625			r = nod(OINDEX, vstat, index);
   626			r->etype = 1;	// no bounds checking
   627			r = nod(ODOT, r, newname(syma));
   628			r = nod(OINDEX, var, r);
   629	
   630			r = nod(OAS, r, a);
   631	
   632			a = nod(OFOR, N, N);
   633			a->nbody = list1(r);
   634	
   635			a->ninit = list1(nod(OAS, index, nodintconst(0)));
   636			a->ntest = nod(OLT, index, nodintconst(t->bound));
   637			a->nincr = nod(OASOP, index, nodintconst(1));
   638			a->nincr->etype = OADD;
   639	
   640			typecheck(&a, Etop);
   641			walkstmt(&a);
   642			*init = list(*init, a);
   643		}
   644	
   645		// put in dynamic entries one-at-a-time
   646		for(l=n->list; l; l=l->next) {
   647			r = l->n;
   648	
   649			if(r->op != OKEY)
   650				fatal("slicelit: rhs not OKEY: %N", r);
   651			index = r->left;
   652			value = r->right;
   653	
   654			if(isliteral(index) && isliteral(value))
   655				continue;
   656	
   657			// build list of var[c] = expr
   658			a = nod(OINDEX, var, r->left);
   659			a = nod(OAS, a, r->right);
   660			typecheck(&a, Etop);
   661			walkexpr(&a, init);
   662			if(nerr != nerrors)
   663				break;
   664	
   665			*init = list(*init, a);
   666		}
   667	}
   668	
   669	void
   670	anylit(int ctxt, Node *n, Node *var, NodeList **init)
   671	{
   672		Type *t;
   673		Node *a, *vstat;
   674	
   675		t = n->type;
   676		switch(n->op) {
   677		default:
   678			fatal("anylit: not lit");
   679	
   680		case OSTRUCTLIT:
   681			if(t->etype != TSTRUCT)
   682				fatal("anylit: not struct");
   683	
   684			if(simplename(var)) {
   685	
   686				if(ctxt == 0) {
   687					// lay out static data
   688					vstat = staticname(t, ctxt);
   689					structlit(ctxt, 1, n, vstat, init);
   690	
   691					// copy static to var
   692					a = nod(OAS, var, vstat);
   693					typecheck(&a, Etop);
   694					walkexpr(&a, init);
   695					*init = list(*init, a);
   696	
   697					// add expressions to automatic
   698					structlit(ctxt, 2, n, var, init);
   699					break;
   700				}
   701				structlit(ctxt, 1, n, var, init);
   702				structlit(ctxt, 2, n, var, init);
   703				break;
   704			}
   705	
   706			// initialize of not completely specified
   707			if(count(n->list) < structcount(t)) {
   708				a = nod(OAS, var, N);
   709				typecheck(&a, Etop);
   710				walkexpr(&a, init);
   711				*init = list(*init, a);
   712			}
   713			structlit(ctxt, 3, n, var, init);
   714			break;
   715	
   716		case OARRAYLIT:
   717			if(t->etype != TARRAY)
   718				fatal("anylit: not array");
   719			if(t->bound < 0) {
   720				slicelit(ctxt, n, var, init);
   721				break;
   722			}
   723	
   724			if(simplename(var)) {
   725	
   726				if(ctxt == 0) {
   727					// lay out static data
   728					vstat = staticname(t, ctxt);
   729					arraylit(1, 1, n, vstat, init);
   730	
   731					// copy static to automatic
   732					a = nod(OAS, var, vstat);
   733					typecheck(&a, Etop);
   734					walkexpr(&a, init);
   735					*init = list(*init, a);
   736	
   737					// add expressions to automatic
   738					arraylit(ctxt, 2, n, var, init);
   739					break;
   740				}
   741				arraylit(ctxt, 1, n, var, init);
   742				arraylit(ctxt, 2, n, var, init);
   743				break;
   744			}
   745	
   746			// initialize of not completely specified
   747			if(count(n->list) < t->bound) {
   748				a = nod(OAS, var, N);
   749				typecheck(&a, Etop);
   750				walkexpr(&a, init);
   751				*init = list(*init, a);
   752			}
   753			arraylit(ctxt, 3, n, var, init);
   754			break;
   755	
   756		case OMAPLIT:
   757			if(t->etype != TMAP)
   758				fatal("anylit: not map");
   759			maplit(ctxt, n, var, init);
   760			break;
   761		}
   762	}
   763	
   764	int
   765	oaslit(Node *n, NodeList **init)
   766	{
   767		int ctxt;
   768	
   769		if(n->left == N || n->right == N)
   770			goto no;
   771		if(n->left->type == T || n->right->type == T)
   772			goto no;
   773		if(!simplename(n->left))
   774			goto no;
   775		if(!eqtype(n->left->type, n->right->type))
   776			goto no;
   777	
   778		// context is init() function.
   779		// implies generated data executed
   780		// exactly once and not subject to races.
   781		ctxt = 0;
   782	//	if(n->dodata == 1)
   783	//		ctxt = 1;
   784	
   785		switch(n->right->op) {
   786		default:
   787			goto no;
   788	
   789		case OSTRUCTLIT:
   790		case OARRAYLIT:
   791		case OMAPLIT:
   792			if(vmatch1(n->left, n->right))
   793				goto no;
   794			anylit(ctxt, n->right, n->left, init);
   795			break;
   796		}
   797		n->op = OEMPTY;
   798		return 1;
   799	
   800	no:
   801		// not a special composit literal assignment
   802		return 0;
   803	}
   804	
   805	static int
   806	getlit(Node *lit)
   807	{
   808		if(smallintconst(lit))
   809			return mpgetfix(lit->val.u.xval);
   810		return -1;
   811	}
   812	
   813	int
   814	stataddr(Node *nam, Node *n)
   815	{
   816		int l;
   817	
   818		if(n == N)
   819			goto no;
   820	
   821		switch(n->op) {
   822	
   823		case ONAME:
   824			*nam = *n;
   825			return n->addable;
   826	
   827		case ODOT:
   828			if(!stataddr(nam, n->left))
   829				break;
   830			nam->xoffset += n->xoffset;
   831			nam->type = n->type;
   832			return 1;
   833	
   834		case OINDEX:
   835			if(n->left->type->bound < 0)
   836				break;
   837			if(!stataddr(nam, n->left))
   838				break;
   839			l = getlit(n->right);
   840			if(l < 0)
   841				break;
   842			nam->xoffset += l*n->type->width;
   843			nam->type = n->type;
   844			return 1;
   845		}
   846	
   847	no:
   848		return 0;
   849	}
   850	
   851	int
   852	gen_as_init(Node *n)
   853	{
   854		Node *nr, *nl;
   855		Node nam, nod1;
   856	
   857		if(n->dodata == 0)
   858			goto no;
   859	
   860		nr = n->right;
   861		nl = n->left;
   862		if(nr == N) {
   863			if(!stataddr(&nam, nl))
   864				goto no;
   865			if(nam.class != PEXTERN)
   866				goto no;
   867			goto yes;
   868		}
   869	
   870		if(nr->type == T || !eqtype(nl->type, nr->type))
   871			goto no;
   872	
   873		if(!stataddr(&nam, nl))
   874			goto no;
   875	
   876		if(nam.class != PEXTERN)
   877			goto no;
   878	
   879		switch(nr->op) {
   880		default:
   881			goto no;
   882	
   883		case OCONVNOP:
   884			nr = nr->left;
   885			if(nr == N || nr->op != OSLICEARR)
   886				goto no;
   887			// fall through
   888		
   889		case OSLICEARR:
   890			if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) {
   891				nr = nr->left;
   892				goto slice;
   893			}
   894			goto no;
   895	
   896		case OLITERAL:
   897			break;
   898		}
   899	
   900		switch(nr->type->etype) {
   901		default:
   902			goto no;
   903	
   904		case TBOOL:
   905		case TINT8:
   906		case TUINT8:
   907		case TINT16:
   908		case TUINT16:
   909		case TINT32:
   910		case TUINT32:
   911		case TINT64:
   912		case TUINT64:
   913		case TINT:
   914		case TUINT:
   915		case TUINTPTR:
   916		case TPTR32:
   917		case TPTR64:
   918		case TFLOAT32:
   919		case TFLOAT64:
   920			gused(N); // in case the data is the dest of a goto
   921			gdata(&nam, nr, nr->type->width);
   922			break;
   923	
   924		case TCOMPLEX64:
   925		case TCOMPLEX128:
   926			gused(N); // in case the data is the dest of a goto
   927			gdatacomplex(&nam, nr->val.u.cval);
   928			break;
   929	
   930		case TSTRING:
   931			gused(N); // in case the data is the dest of a goto
   932			gdatastring(&nam, nr->val.u.sval);
   933			break;
   934		}
   935	
   936	yes:
   937		return 1;
   938	
   939	slice:
   940		gused(N); // in case the data is the dest of a goto
   941		nl = nr;
   942		if(nr == N || nr->op != OADDR)
   943			goto no;
   944		nr = nr->left;
   945		if(nr == N || nr->op != ONAME)
   946			goto no;
   947	
   948		// nr is the array being converted to a slice
   949		if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
   950			goto no;
   951	
   952		nam.xoffset += Array_array;
   953		gdata(&nam, nl, types[tptr]->width);
   954	
   955		nam.xoffset += Array_nel-Array_array;
   956		nodconst(&nod1, types[TINT32], nr->type->bound);
   957		gdata(&nam, &nod1, types[TINT32]->width);
   958	
   959		nam.xoffset += Array_cap-Array_nel;
   960		gdata(&nam, &nod1, types[TINT32]->width);
   961	
   962		goto yes;
   963	
   964	no:
   965		if(n->dodata == 2) {
   966			dump("\ngen_as_init", n);
   967			fatal("gen_as_init couldnt make data statement");
   968		}
   969		return 0;
   970	}
   971	

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.