461 lines · 7.6 KB · Brainfuck
RawDownload
## Manage module Data Section.# MP_INT,MP_LONG,MP_REAL,MP_STRING,MP_CASE,MP_GOTO:	con iota; Datum_v: adt {	ival:	big;		# MP_[INT|LONG]	rval:	real;		# MP_REAL	next:	cyclic ref Datum.Pv;}; Datum_c: adt {			# MP_CASE	n:	int;		# number of cases in jmptbl	jmptbl: array of int;	# 3 words per case, plus default}; Datum_g: adt {			# MP_GOTO (for finally blocks)	n:	int;		# number of entries in gototbl	gototbl:array of int;}; Datum: adt {	kind:	byte;				# MP_INT, etc.	offset:	int;				# byte offset in Data Section	next:	cyclic ref Datum;	pick {		Pv =>			v:	ref Datum_v;	# MP_[INT|LONG|REAL]		Ps =>			s:	string;		# MP_STRING		Pc =>			c:	ref Datum_c;	# MP_CASE		Pg =>			g:	ref Datum_g;	# MP_GOTO	}}; Hentry: adt {	md:	ref Datum.Ps;	next:	cyclic ref Hentry;}; htable :=	array [Hashsize] of ref Hentry;mpoff  :=	IBY2WD; # skip first cell, as it's reserved for nil ptr mplist:		ref Datum;mptail:		ref Datum;llist:		ref Datum.Pv;rlist:		ref Datum.Pv; ## Append a module datum to mplist.# append(md: ref Datum){	if(mplist == nil)		mplist = md;	else		mptail.next = md;	mptail = md;} ## Add a 'byte', int 'word', or 'long'.# mpintegral(kind: int, ival: big): int{	size: int; 	md := ref Datum.Pv;	md.v = ref Datum_v;	md.v.ival = ival;	case kind {	MP_INT =>		md.kind = byte MP_INT;		size = IBY2WD;		mpoff = align(mpoff, IBY2WD);	MP_LONG =>		md.kind = byte MP_LONG;		size = IBY2LG;		mpoff = align(mpoff, IBY2LG);		md.v.next = llist;		llist = md;	}	md.offset = mpoff;	mpoff += size;	append(md);	return md.offset;} ## Add a 'word' (int).# mpint(ival: int): int{	return mpintegral(MP_INT, big ival);} ## Add a 'long'.# mplong(lval: big): int{	md: ref Datum.Pv; 	for(md = llist; md != nil; md = md.v.next) {		if(lval == md.v.ival)			return md.offset;	}	return mpintegral(MP_LONG, lval);} ## Add a 'real'.# mpreal(rval: real): int{	md: ref Datum.Pv; 	for(md = rlist; md != nil; md = md.v.next) {		# distinguish 0.0 from -0.0		if(rval == md.v.rval		&& math->realbits64(rval) == math->realbits64(md.v.rval))			return md.offset;	}	md = ref Datum.Pv;	md.kind = byte MP_REAL;	md.v = ref Datum_v;	md.v.rval = rval;	md.v.next = rlist;	rlist = md;	mpoff = align(mpoff, IBY2FT);	md.offset = mpoff;	mpoff += IBY2FT;	append(md);	return md.offset;} ## Add a 'case' jump table.# mpcase(sz: int, jt: array of int): int{	md := ref Datum.Pc;	md.kind = byte MP_CASE;	mpoff = align(mpoff, IBY2WD);	md.offset = mpoff;	mpoff += (sz*3+2)*IBY2WD;	md.c = ref Datum_c;	md.c.n = sz;	md.c.jmptbl = jt;	append(md);	return md.offset;} ## Add a 'goto' jump table; used for implementing finally blocks.# mpgoto(n: int, gototbl: array of int): int{	md := ref Datum.Pg;	md.kind = byte MP_GOTO;	mpoff = align(mpoff, IBY2WD);	md.offset = mpoff;	mpoff += (n+2)*IBY2WD;	md.g = ref Datum_g;	md.g.n = n;	md.g.gototbl = gototbl;	append(md);	return md.offset+IBY2WD;} ## Hash table lookup function.# htlook(s: string): ref Hentry{	he: ref Hentry; 	for(he = htable[hashval(s)]; he != nil; he = he.next)		if(s == he.md.s)			return he;	return nil;} ## Hash table enter function.# htenter(md: ref Datum.Ps): ref Hentry{	h: int;	he: ref Hentry; 	h = hashval(md.s);	he = ref Hentry(md, htable[h]);	htable[h] = he;	return he;} ## Add a 'string'.# mpstring(s: string): int{	he: ref Hentry;	md: ref Datum.Ps; 	if((he = htlook(s)) != nil)		return he.md.offset;	md = ref Datum.Ps;	md.kind = byte MP_STRING;	md.s = s;	mpoff = align(mpoff, IBY2WD);	md.offset = mpoff;	mpoff += IBY2WD;	append(md);	htenter(md);	return md.offset;} ## Calculate the type descriptor for the Module Data section.# mpdesc(){	md: ref Datum;	ltsize, rtsize, ln, mdsize: int;	map: array of byte; 	ltsize = LTrelocsize();		# link-time reloc data	mpoff = align(mpoff, IBY2WD);	rtsize = RTrelocsize();		# run-time reloc data	mdsize = ltsize + mpoff + rtsize;	ln = mdsize / (8*IBY2WD) + (mdsize % (8*IBY2WD) != 0);	map = array [ln] of { * => byte 0 };	LTrelocdesc(map);	for(md = mplist; md != nil; md = md.next) {		if(int md.kind == MP_STRING)			setbit(map, ltsize + md.offset);	}	RTrelocdesc(map, ltsize + mpoff);	RTfixoff(ltsize + mpoff);	mpdescid(mdsize, ln, map);} asmprefix(off: int, s: string){	bout.puts("\t" + s + "\t@mp+" + string off + ",");} ## Begin an array initializer.# asmarray(off: int, tid: int, nelt: int, reloff: int){	asmprefix(off, "array");	bout.puts("$" + string tid + "," + string nelt + "\n");	asmprefix(off, "indir");	bout.puts(string reloff + "\n");} asmint(off: int, val: int){	asmprefix(off, "word");	bout.puts(string val + "\n");} asmlong(off: int, val: big){	asmprefix(off, "long");	bout.puts(string val + "\n");} asmreal(off: int, val: real){	asmprefix(off, "real");	bout.puts(string val + "\n");} asmstring(off: int, s: string){	asmprefix(off, "string");	bout.putc('"');	pstring(s);	bout.puts("\"\n");} asmcase(off: int, md: ref Datum.Pc){	i: int; 	asmprefix(off, "word");	bout.puts(string md.c.n);	for(i = 0; i < md.c.n; i++) {		bout.puts("," + string md.c.jmptbl[i*3]);		bout.puts("," + string md.c.jmptbl[i*3+1]);		bout.puts("," + string md.c.jmptbl[i*3+2]);	}	bout.puts("," + string md.c.jmptbl[md.c.n*3] + "\n");} asmgoto(off: int, md: ref Datum.Pg){	i: int; 	asmprefix(off, "word");	bout.puts(string md.g.n);	for(i = 0; i < md.g.n; i++)		bout.puts("," + string md.g.gototbl[i]);	bout.putc('\n');} ## Write Module Data to .s file.# asmvar(){	md: ref Datum;	ltsize, rtsize, off: int; 	ltsize = LTrelocsize();	rtsize = RTrelocsize();	bout.puts("\tvar\t@mp," + string(ltsize + mpoff + rtsize) + "\n");	off = asmthisCreloc(0);	asmint(off, mpoff + rtsize);	off += IBY2WD;	asmDreloc(off);	off += IBY2WD;	off = asmCreloc(off);	off = align(off, 32);	if(off != ltsize)		fatal("asmvar: off " + string off + ", " + string ltsize); 	for(md = mplist; md != nil; md = md.next) {		off = ltsize + md.offset;		pick mdp := md {		Pv =>			case int mdp.kind {			MP_INT =>				asmint(off, int mdp.v.ival);			MP_LONG =>				asmlong(off, mdp.v.ival);			MP_REAL =>				asmreal(off, mdp.v.rval);			}		Ps =>			asmstring(off, mdp.s);		Pc =>			asmcase(off, mdp);		Pg =>			asmgoto(off, mdp);		* =>			badpick("asmvar");		}	}	asmRTClass(ltsize + mpoff);} ## Put Module Data size into .dis Header.# disnvar(){	discon(LTrelocsize() + mpoff + RTrelocsize());} discase(off: int, md: ref Datum.Pc){	i: int; 	disint(off, md.c.n);	off += IBY2WD;	for(i = 0; i < md.c.n; i++) {		disint(off, md.c.jmptbl[i*3]);		off += IBY2WD;		disint(off, md.c.jmptbl[i*3+1]);		off += IBY2WD;		disint(off, md.c.jmptbl[i*3+2]);		off += IBY2WD;	}	disint(off, md.c.jmptbl[md.c.n*3]);} disgoto(off: int, md: ref Datum.Pg){	i: int; 	disint(off, md.g.n);	for(i = 0; i < md.g.n; i++) {		off += IBY2WD;		disint(off, md.g.gototbl[i]);	}} ## Write Module Data to .dis file.# disvar(){	md: ref Datum;	ltsize, rtsize, off: int; 	ltsize = LTrelocsize();	rtsize = RTrelocsize();	off = disthisCreloc(0);	disint(off, mpoff + rtsize);	off += IBY2WD;	disDreloc(off);	off += IBY2WD;	off = disCreloc(off);	off = align(off, 32);	if(off != ltsize)		fatal("disvar: off " + string off + ", ltsize " + string ltsize); 	for(md = mplist; md != nil; md = md.next) {		off = ltsize + md.offset;		pick mdp := md {		Pv =>			case int mdp.kind {			MP_INT =>				disint(off, int mdp.v.ival);			MP_LONG =>				dislong(off, mdp.v.ival);			MP_REAL =>				disreal(off, mdp.v.rval);			}		Ps =>			disstring(off, mdp.s);		Pc =>			discase(off, mdp);		Pg =>			disgoto(off, mdp);		* =>			badpick("disvar");		}	}	disRTClass(ltsize + mpoff);	disflush(-1, -1, 0);	bout.putb(byte 0);}