Exemple #1
0
// p is a call instruction. Does the call fail to return?
int
noreturn(Prog *p)
{
	Sym *s;
	int i;
	static Sym*	symlist[10];

	if(symlist[0] == S) {
		symlist[0] = pkglookup("panicindex", runtimepkg);
		symlist[1] = pkglookup("panicslice", runtimepkg);
		symlist[2] = pkglookup("throwinit", runtimepkg);
		symlist[3] = pkglookup("panic", runtimepkg);
		symlist[4] = pkglookup("panicwrap", runtimepkg);
		symlist[5] = pkglookup("throwreturn", runtimepkg);
		symlist[6] = pkglookup("selectgo", runtimepkg);
		symlist[7] = pkglookup("block", runtimepkg);
	}

	if(p->to.node == nil)
		return 0;
	s = p->to.node->sym;
	if(s == S)
		return 0;
	for(i=0; symlist[i]!=S; i++)
		if(s == symlist[i])
			return 1;
	return 0;
}
Exemple #2
0
void
slicebytes(Node *nam, char *s, int len)
{
	int off, n, m;
	static int gen;
	Sym *sym;

	snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen);
	sym = pkglookup(namebuf, localpkg);
	sym->def = newname(sym);

	off = 0;
	for(n=0; n<len; n+=m) {
		m = 8;
		if(m > len-n)
			m = len-n;
		off = dsname(sym, off, s+n, m);
	}
	ggloblsym(sym, off, 0, 0);
	
	if(nam->op != ONAME)
		fatal("slicebytes %N", nam);
	off = nam->xoffset;
	off = dsymptr(nam->sym, off, sym, 0);
	off = duintxx(nam->sym, off, len, widthint);
	duintxx(nam->sym, off, len, widthint);
}
Exemple #3
0
Sym*
stringsym(char *s, int len)
{
	static int gen;
	Sym *sym;
	int off, n, m;
	struct {
		Strlit lit;
		char buf[110];
	} tmp;
	Pkg *pkg;

	if(len > 100) {
		// huge strings are made static to avoid long names
		snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
		pkg = localpkg;
	} else {
		// small strings get named by their contents,
		// so that multiple modules using the same string
		// can share it.
		tmp.lit.len = len;
		memmove(tmp.lit.s, s, len);
		tmp.lit.s[len] = '\0';
		snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
		pkg = gostringpkg;
	}
	sym = pkglookup(namebuf, pkg);
	
	// SymUniq flag indicates that data is generated already
	if(sym->flags & SymUniq)
		return sym;
	sym->flags |= SymUniq;
	sym->def = newname(sym);

	off = 0;
	
	// string header
	off = dsymptr(sym, off, sym, widthptr+widthint);
	off = duintxx(sym, off, len, widthint);
	
	// string data
	for(n=0; n<len; n+=m) {
		m = 8;
		if(m > len-n)
			m = len-n;
		off = dsname(sym, off, s+n, m);
	}
	off = duint8(sym, off, 0);  // terminating NUL for runtime
	off = (off+widthptr-1)&~(widthptr-1);  // round to pointer alignment
	ggloblsym(sym, off, 1, 1);

	return sym;	
}
Exemple #4
0
int
noreturn(Prog *p)
{
	Sym *s;
	int i;

	if(symlist[0] == S) {
		symlist[0] = pkglookup("panicindex", runtimepkg);
		symlist[1] = pkglookup("panicslice", runtimepkg);
		symlist[2] = pkglookup("throwinit", runtimepkg);
		symlist[3] = pkglookup("panic", runtimepkg);
	}

	s = p->to.sym;
	if(s == S)
		return 0;
	for(i=0; symlist[i]!=S; i++)
		if(s == symlist[i])
			return 1;
	return 0;
}
Exemple #5
0
void
typeinit(void)
{
	int i, etype, sameas;
	Type *t;
	Sym *s, *s1;

	if(widthptr == 0)
		fatal("typeinit before betypeinit");

	for(i=0; i<NTYPE; i++)
		simtype[i] = i;

	types[TPTR32] = typ(TPTR32);
	dowidth(types[TPTR32]);

	types[TPTR64] = typ(TPTR64);
	dowidth(types[TPTR64]);
	
	t = typ(TUNSAFEPTR);
	types[TUNSAFEPTR] = t;
	t->sym = pkglookup("Pointer", unsafepkg);
	t->sym->def = typenod(t);
	
	dowidth(types[TUNSAFEPTR]);

	tptr = TPTR32;
	if(widthptr == 8)
		tptr = TPTR64;

	for(i=TINT8; i<=TUINT64; i++)
		isint[i] = 1;
	isint[TINT] = 1;
	isint[TUINT] = 1;
	isint[TUINTPTR] = 1;

	isfloat[TFLOAT32] = 1;
	isfloat[TFLOAT64] = 1;

	iscomplex[TCOMPLEX64] = 1;
	iscomplex[TCOMPLEX128] = 1;

	isptr[TPTR32] = 1;
	isptr[TPTR64] = 1;

	isforw[TFORW] = 1;

	issigned[TINT] = 1;
	issigned[TINT8] = 1;
	issigned[TINT16] = 1;
	issigned[TINT32] = 1;
	issigned[TINT64] = 1;

	/*
	 * initialize okfor
	 */
	for(i=0; i<NTYPE; i++) {
		if(isint[i] || i == TIDEAL) {
			okforeq[i] = 1;
			okforcmp[i] = 1;
			okforarith[i] = 1;
			okforadd[i] = 1;
			okforand[i] = 1;
			okforconst[i] = 1;
			issimple[i] = 1;
			minintval[i] = mal(sizeof(*minintval[i]));
			maxintval[i] = mal(sizeof(*maxintval[i]));
		}
		if(isfloat[i]) {
			okforeq[i] = 1;
			okforcmp[i] = 1;
			okforadd[i] = 1;
			okforarith[i] = 1;
			okforconst[i] = 1;
			issimple[i] = 1;
			minfltval[i] = mal(sizeof(*minfltval[i]));
			maxfltval[i] = mal(sizeof(*maxfltval[i]));
		}
		if(iscomplex[i]) {
			okforeq[i] = 1;
			okforadd[i] = 1;
			okforarith[i] = 1;
			okforconst[i] = 1;
			issimple[i] = 1;
		}
	}

	issimple[TBOOL] = 1;

	okforadd[TSTRING] = 1;

	okforbool[TBOOL] = 1;

	okforcap[TARRAY] = 1;
	okforcap[TCHAN] = 1;

	okforconst[TBOOL] = 1;
	okforconst[TSTRING] = 1;

	okforlen[TARRAY] = 1;
	okforlen[TCHAN] = 1;
	okforlen[TMAP] = 1;
	okforlen[TSTRING] = 1;

	okforeq[TPTR32] = 1;
	okforeq[TPTR64] = 1;
	okforeq[TUNSAFEPTR] = 1;
	okforeq[TINTER] = 1;
	okforeq[TCHAN] = 1;
	okforeq[TSTRING] = 1;
	okforeq[TBOOL] = 1;
	okforeq[TMAP] = 1;	// nil only; refined in typecheck
	okforeq[TFUNC] = 1;	// nil only; refined in typecheck
	okforeq[TARRAY] = 1;	// nil slice only; refined in typecheck
	okforeq[TSTRUCT] = 1;	// it's complicated; refined in typecheck

	okforcmp[TSTRING] = 1;

	for(i=0; i<nelem(okfor); i++)
		okfor[i] = okfornone;

	// binary
	okfor[OADD] = okforadd;
	okfor[OAND] = okforand;
	okfor[OANDAND] = okforbool;
	okfor[OANDNOT] = okforand;
	okfor[ODIV] = okforarith;
	okfor[OEQ] = okforeq;
	okfor[OGE] = okforcmp;
	okfor[OGT] = okforcmp;
	okfor[OLE] = okforcmp;
	okfor[OLT] = okforcmp;
	okfor[OMOD] = okforand;
	okfor[OMUL] = okforarith;
	okfor[ONE] = okforeq;
	okfor[OOR] = okforand;
	okfor[OOROR] = okforbool;
	okfor[OSUB] = okforarith;
	okfor[OXOR] = okforand;
	okfor[OLSH] = okforand;
	okfor[ORSH] = okforand;

	// unary
	okfor[OCOM] = okforand;
	okfor[OMINUS] = okforarith;
	okfor[ONOT] = okforbool;
	okfor[OPLUS] = okforarith;

	// special
	okfor[OCAP] = okforcap;
	okfor[OLEN] = okforlen;

	// comparison
	iscmp[OLT] = 1;
	iscmp[OGT] = 1;
	iscmp[OGE] = 1;
	iscmp[OLE] = 1;
	iscmp[OEQ] = 1;
	iscmp[ONE] = 1;

	mpatofix(maxintval[TINT8], "0x7f");
	mpatofix(minintval[TINT8], "-0x80");
	mpatofix(maxintval[TINT16], "0x7fff");
	mpatofix(minintval[TINT16], "-0x8000");
	mpatofix(maxintval[TINT32], "0x7fffffff");
	mpatofix(minintval[TINT32], "-0x80000000");
	mpatofix(maxintval[TINT64], "0x7fffffffffffffff");
	mpatofix(minintval[TINT64], "-0x8000000000000000");

	mpatofix(maxintval[TUINT8], "0xff");
	mpatofix(maxintval[TUINT16], "0xffff");
	mpatofix(maxintval[TUINT32], "0xffffffff");
	mpatofix(maxintval[TUINT64], "0xffffffffffffffff");

	/* f is valid float if min < f < max.  (min and max are not themselves valid.) */
	mpatoflt(maxfltval[TFLOAT32], "33554431p103");	/* 2^24-1 p (127-23) + 1/2 ulp*/
	mpatoflt(minfltval[TFLOAT32], "-33554431p103");
	mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970");	/* 2^53-1 p (1023-52) + 1/2 ulp */
	mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");

	maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32];
	minfltval[TCOMPLEX64] = minfltval[TFLOAT32];
	maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64];
	minfltval[TCOMPLEX128] = minfltval[TFLOAT64];

	/* for walk to use in error messages */
	types[TFUNC] = functype(N, nil, nil);

	/* types used in front end */
	// types[TNIL] got set early in lexinit
	types[TIDEAL] = typ(TIDEAL);
	types[TINTER] = typ(TINTER);

	/* simple aliases */
	simtype[TMAP] = tptr;
	simtype[TCHAN] = tptr;
	simtype[TFUNC] = tptr;
	simtype[TUNSAFEPTR] = tptr;

	/* pick up the backend typedefs */
	for(i=0; typedefs[i].name; i++) {
		s = lookup(typedefs[i].name);
		s1 = pkglookup(typedefs[i].name, builtinpkg);

		etype = typedefs[i].etype;
		if(etype < 0 || etype >= nelem(types))
			fatal("typeinit: %s bad etype", s->name);
		sameas = typedefs[i].sameas;
		if(sameas < 0 || sameas >= nelem(types))
			fatal("typeinit: %s bad sameas", s->name);
		simtype[etype] = sameas;
		minfltval[etype] = minfltval[sameas];
		maxfltval[etype] = maxfltval[sameas];
		minintval[etype] = minintval[sameas];
		maxintval[etype] = maxintval[sameas];

		t = types[etype];
		if(t != T)
			fatal("typeinit: %s already defined", s->name);

		t = typ(etype);
		t->sym = s1;

		dowidth(t);
		types[etype] = t;
		s1->def = typenod(t);
	}

	Array_array = rnd(0, widthptr);
	Array_nel = rnd(Array_array+widthptr, widthint);
	Array_cap = rnd(Array_nel+widthint, widthint);
	sizeof_Array = rnd(Array_cap+widthint, widthptr);

	// string is same as slice wo the cap
	sizeof_String = rnd(Array_nel+widthint, widthptr);

	dowidth(types[TSTRING]);
	dowidth(idealstring);
}
Exemple #6
0
void
dumpobj(void)
{
	NodeList *externs, *tmp;
	char arhdr[ArhdrSize];
	vlong startobj, size;
	Sym *zero;

	bout = Bopen(outfile, OWRITE);
	if(bout == nil) {
		flusherrors();
		print("can't create %s: %r\n", outfile);
		errorexit();
	}

	startobj = 0;
	if(writearchive) {
		Bwrite(bout, "!<arch>\n", 8);
		memset(arhdr, 0, sizeof arhdr);
		Bwrite(bout, arhdr, sizeof arhdr);
		startobj = Boffset(bout);
	}
	Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	dumpexport();
	
	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		formathdr(arhdr, "__.PKGDEF", size);
		Bwrite(bout, arhdr, ArhdrSize);
		Bflush(bout);

		Bseek(bout, startobj + size + (size&1), 0);
		memset(arhdr, 0, ArhdrSize);
		Bwrite(bout, arhdr, ArhdrSize);
		startobj = Boffset(bout);
		Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	}

	Bprint(bout, "\n!\n");

	externs = nil;
	if(externdcl != nil)
		externs = externdcl->end;

	dumpglobls();
	dumptypestructs();

	// Dump extra globals.
	tmp = externdcl;
	if(externs != nil)
		externdcl = externs->next;
	dumpglobls();
	externdcl = tmp;

	zero = pkglookup("zerovalue", runtimepkg);
	ggloblsym(zero, zerosize, 1, 1);

	dumpdata();
	writeobj(ctxt, bout);

	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		snprint(namebuf, sizeof namebuf, "_go_.%c", thechar);
		formathdr(arhdr, namebuf, size);
		Bwrite(bout, arhdr, ArhdrSize);
	}
	Bterm(bout);
}
Exemple #7
0
/*
 * make a refer to the string sval,
 * emitting DATA if needed.
 */
void
datagostring(Strlit *sval, Addr *a)
{
	Prog *p;
	Addr ac, ao, ap;
	int32 wi, wp;
	static int gen;

	memset(&ac, 0, sizeof(ac));
	memset(&ao, 0, sizeof(ao));
	memset(&ap, 0, sizeof(ap));

	// constant
	ac.type = D_CONST;
	ac.name = D_NONE;
	ac.offset = 0;			// fill in
	ac.reg = NREG;

	// string len+ptr
	ao.type = D_OREG;
	ao.name = D_STATIC;		// fill in
	ao.etype = TINT32;
	ao.sym = nil;			// fill in
	ao.reg = NREG;

	// $string len+ptr
	datastring(sval->s, sval->len, &ap);
	ap.type = D_CONST;
	ap.etype = TINT32;

	wi = types[TUINT32]->width;
	wp = types[tptr]->width;

	if(ap.name == D_STATIC) {
		// huge strings are made static to avoid long names
		snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
		ao.sym = lookup(namebuf);
		ao.name = D_STATIC;
	} else {
		// small strings get named by their contents,
		// so that multiple modules using the same string
		// can share it.
		snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval);
		ao.sym = pkglookup(namebuf, gostringpkg);
		ao.name = D_EXTERN;
	}

	*a = ao;
	if(ao.sym->flags & SymUniq)
		return;
	ao.sym->flags |= SymUniq;

	data();
	// DATA gostring, wp, $cstring
	p = pc;
	gins(ADATA, N, N);
	p->from = ao;
	p->reg = wp;
	p->to = ap;

	// DATA gostring+wp, wi, $len
	p = pc;
	gins(ADATA, N, N);
	p->from = ao;
	p->from.offset = wp;
	p->reg = wi;
	p->to = ac;
	p->to.offset = sval->len;

	p = pc;
	ggloblsym(ao.sym, types[TSTRING]->width, ao.name == D_EXTERN);
	if(ao.name == D_STATIC)
		p->from.name = D_STATIC;
	text();
}
Exemple #8
0
/*
 * make a refer to the data s, s+len
 * emitting DATA if needed.
 */
void
datastring(char *s, int len, Addr *a)
{
	int w;
	Prog *p;
	Addr ac, ao;
	static int gen;
	struct {
		Strlit lit;
		char buf[100];
	} tmp;

	// string
	memset(&ao, 0, sizeof(ao));
	ao.type = D_OREG;
	ao.name = D_STATIC;
	ao.etype = TINT32;
	ao.offset = 0;		// fill in
	ao.reg = NREG;

	// constant
	memset(&ac, 0, sizeof(ac));
	ac.type = D_CONST;
	ac.name = D_NONE;
	ac.offset = 0;		// fill in
	ac.reg = NREG;

	// huge strings are made static to avoid long names.
	if(len > 100) {
		snprint(namebuf, sizeof(namebuf), ".string.%d", gen++);
		ao.sym = lookup(namebuf);
		ao.name = D_STATIC;
	} else {
		if(len > 0 && s[len-1] == '\0')
			len--;
		tmp.lit.len = len;
		memmove(tmp.lit.s, s, len);
		tmp.lit.s[len] = '\0';
		len++;
		snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
		ao.sym = pkglookup(namebuf, stringpkg);
		ao.name = D_EXTERN;
	}
	*a = ao;

	// only generate data the first time.
	if(ao.sym->flags & SymUniq)
		return;
	ao.sym->flags |= SymUniq;

	data();
	for(w=0; w<len; w+=8) {
		p = pc;
		gins(ADATA, N, N);

		// DATA s+w, [NSNAME], $"xxx"
		p->from = ao;
		p->from.offset = w;

		p->reg = NSNAME;
		if(w+8 > len)
			p->reg = len-w;

		p->to = ac;
		p->to.type = D_SCONST;
		p->to.offset = len;
		memmove(p->to.sval, s+w, p->reg);
	}
	p = pc;
	ggloblsym(ao.sym, len, ao.name == D_EXTERN);
	if(ao.name == D_STATIC)
		p->from.name = D_STATIC;
	text();
}
Exemple #9
0
void
typeinit(void)
{
	int i, etype, sameas;
	Type *t;
	Sym *s, *s1;

	if(widthptr == 0)
		fatal("typeinit before betypeinit");

	for(i=0; i<NTYPE; i++)
		simtype[i] = i;

	types[TPTR32] = typ(TPTR32);
	dowidth(types[TPTR32]);

	types[TPTR64] = typ(TPTR64);
	dowidth(types[TPTR64]);

	tptr = TPTR32;
	if(widthptr == 8)
		tptr = TPTR64;

	for(i=TINT8; i<=TUINT64; i++)
		isint[i] = 1;
	isint[TINT] = 1;
	isint[TUINT] = 1;
	isint[TUINTPTR] = 1;

	for(i=TFLOAT32; i<=TFLOAT64; i++)
		isfloat[i] = 1;
	isfloat[TFLOAT] = 1;

	isptr[TPTR32] = 1;
	isptr[TPTR64] = 1;

	isforw[TFORW] = 1;

	issigned[TINT] = 1;
	issigned[TINT8] = 1;
	issigned[TINT16] = 1;
	issigned[TINT32] = 1;
	issigned[TINT64] = 1;

	/*
	 * initialize okfor
	 */
	for(i=0; i<NTYPE; i++) {
		if(isint[i] || i == TIDEAL) {
			okforeq[i] = 1;
			okforcmp[i] = 1;
			okforarith[i] = 1;
			okforadd[i] = 1;
			okforand[i] = 1;
			issimple[i] = 1;
			minintval[i] = mal(sizeof(*minintval[i]));
			maxintval[i] = mal(sizeof(*maxintval[i]));
		}
		if(isfloat[i]) {
			okforeq[i] = 1;
			okforcmp[i] = 1;
			okforadd[i] = 1;
			okforarith[i] = 1;
			issimple[i] = 1;
			minfltval[i] = mal(sizeof(*minfltval[i]));
			maxfltval[i] = mal(sizeof(*maxfltval[i]));
		}
	}

	issimple[TBOOL] = 1;

	okforadd[TSTRING] = 1;

	okforbool[TBOOL] = 1;

	okforcap[TARRAY] = 1;
	okforcap[TCHAN] = 1;

	okforlen[TARRAY] = 1;
	okforlen[TCHAN] = 1;
	okforlen[TMAP] = 1;
	okforlen[TSTRING] = 1;

	okforeq[TPTR32] = 1;
	okforeq[TPTR64] = 1;
	okforeq[TINTER] = 1;
	okforeq[TMAP] = 1;
	okforeq[TCHAN] = 1;
	okforeq[TFUNC] = 1;
	okforeq[TSTRING] = 1;
	okforeq[TBOOL] = 1;
	okforeq[TARRAY] = 1;	// refined in typecheck

	okforcmp[TSTRING] = 1;

	for(i=0; i<nelem(okfor); i++)
		okfor[i] = okfornone;

	// binary
	okfor[OADD] = okforadd;
	okfor[OAND] = okforand;
	okfor[OANDAND] = okforbool;
	okfor[OANDNOT] = okforand;
	okfor[ODIV] = okforarith;
	okfor[OEQ] = okforeq;
	okfor[OGE] = okforcmp;
	okfor[OGT] = okforcmp;
	okfor[OLE] = okforcmp;
	okfor[OLT] = okforcmp;
	okfor[OMOD] = okforarith;
	okfor[OMUL] = okforarith;
	okfor[ONE] = okforeq;
	okfor[OOR] = okforand;
	okfor[OOROR] = okforbool;
	okfor[OSUB] = okforarith;
	okfor[OXOR] = okforand;
	okfor[OLSH] = okforand;
	okfor[ORSH] = okforand;

	// unary
	okfor[OCOM] = okforand;
	okfor[OMINUS] = okforarith;
	okfor[ONOT] = okforbool;
	okfor[OPLUS] = okforadd;

	// special
	okfor[OCAP] = okforcap;
	okfor[OLEN] = okforlen;

	// comparison
	iscmp[OLT] = 1;
	iscmp[OGT] = 1;
	iscmp[OGE] = 1;
	iscmp[OLE] = 1;
	iscmp[OEQ] = 1;
	iscmp[ONE] = 1;

	mpatofix(maxintval[TINT8], "0x7f");
	mpatofix(minintval[TINT8], "-0x80");
	mpatofix(maxintval[TINT16], "0x7fff");
	mpatofix(minintval[TINT16], "-0x8000");
	mpatofix(maxintval[TINT32], "0x7fffffff");
	mpatofix(minintval[TINT32], "-0x80000000");
	mpatofix(maxintval[TINT64], "0x7fffffffffffffff");
	mpatofix(minintval[TINT64], "-0x8000000000000000");

	mpatofix(maxintval[TUINT8], "0xff");
	mpatofix(maxintval[TUINT16], "0xffff");
	mpatofix(maxintval[TUINT32], "0xffffffff");
	mpatofix(maxintval[TUINT64], "0xffffffffffffffff");

	mpatoflt(maxfltval[TFLOAT32], "3.40282347e+38");
	mpatoflt(minfltval[TFLOAT32], "-3.40282347e+38");
	mpatoflt(maxfltval[TFLOAT64], "1.7976931348623157e+308");
	mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308");

	/* for walk to use in error messages */
	types[TFUNC] = functype(N, nil, nil);

	/* types used in front end */
	// types[TNIL] got set early in lexinit
	types[TIDEAL] = typ(TIDEAL);

	/* simple aliases */
	simtype[TMAP] = tptr;
	simtype[TCHAN] = tptr;
	simtype[TFUNC] = tptr;

	/* pick up the backend typedefs */
	for(i=0; typedefs[i].name; i++) {
		s = lookup(typedefs[i].name);
		s1 = pkglookup(typedefs[i].name, "/builtin/");

		etype = typedefs[i].etype;
		if(etype < 0 || etype >= nelem(types))
			fatal("typeinit: %s bad etype", s->name);
		sameas = typedefs[i].sameas;
		if(sameas < 0 || sameas >= nelem(types))
			fatal("typeinit: %s bad sameas", s->name);
		simtype[etype] = sameas;
		minfltval[etype] = minfltval[sameas];
		maxfltval[etype] = maxfltval[sameas];
		minintval[etype] = minintval[sameas];
		maxintval[etype] = maxintval[sameas];

		t = types[etype];
		if(t != T)
			fatal("typeinit: %s already defined", s->name);

		t = typ(etype);
		t->sym = s;

		dowidth(t);
		types[etype] = t;
		s1->def = typenod(t);
	}

	Array_array = rnd(0, widthptr);
	Array_nel = rnd(Array_array+widthptr, types[TUINT32]->width);
	Array_cap = rnd(Array_nel+types[TUINT32]->width, types[TUINT32]->width);
	sizeof_Array = rnd(Array_cap+types[TUINT32]->width, maxround);

	// string is same as slice wo the cap
	sizeof_String = rnd(Array_nel+types[TUINT32]->width, maxround);

	dowidth(types[TSTRING]);
	dowidth(idealstring);
}