434 lines · 5.6 KB · Brainfuck
RawDownload
## Utility functions.# codeix:	array of byte;ix:	int; uSet(x: array of byte){	codeix = x;	ix = 0;} boundscheck(n: int){	if(ix+n-1 >= len codeix)		verifyerrormess("Attribute bounds");} uPtr(i: int): array of byte{	boundscheck(i);	return codeix[ix:ix+i];} uN(i: int){	ix += i;} u1(): byte{	boundscheck(1);	return codeix[ix++];} u2(): int{	l: int; 	boundscheck(2);	l = (int(codeix[ix])<<8) | int(codeix[ix+1]);	ix += 2;	return l;} u4(): int{	l: int; 	boundscheck(4);	l = (int(codeix[ix])<<24) | (int(codeix[ix+1])<<16)		| (int(codeix[ix+2])<<8) | int(codeix[ix+3]);	ix += 4;	return l;} getattr(): ref Attr{	a := ref Attr(0, 0, nil);	a.name = u2();	verifycpindex(nil, a.name, 1 << CON_Utf8);	a.ln = u4();	boundscheck(a.ln);	a.info = array [a.ln] of byte;	a.info[:] = codeix[ix:ix+a.ln];	ix += a.ln;	return a;} ## Get the constantvalue_index of a ConstantValue attribute.# CVattrindex(fp: ref Field): int{	i: int;	a: ref Attr; 	for(i = 0; i < fp.attr_count; i++) {		a = fp.attr_info[i];		if(STRING(a.name) != "ConstantValue")			continue;		if(a.ln != 2)			verifyerrormess("ConstantValue attribute");		return ((int a.info[0])<<8) | int a.info[1];	}	return 0;} ## Align 'off' on an 'align'-byte boundary ('align' is a power of 2).# align(off: int, align: int): int{	align--;	return (off + align) & ~align;} ## Set 'offset' bit in type descriptor 'map'.# setbit(map: array of byte, offset: int){	map[offset / (8*IBY2WD)] |= byte(1 << (7 - (offset / IBY2WD % 8)));} ## Trivial hash function from asm.# hashval(s: string): int{	h, i: int; 	h = 0;	for(i = 0; i < len s; i++)		h = h*3 + s[i];	if(h < 0)		h = -h;	return h % Hashsize;} ## Advance to the next Java type in a method descriptor.# nextjavatype(s: string): string{	nlb: int; 	nlb = 0;	while(1) {		case s[0] {		'L' =>			(nil, s) = str->splitl(s, ";");			return s[1:];		'V' or		'Z' or		'B' or		'C' or		'S' or		'I' or		'J' or		'F' or		'D' =>			return s[1:];		'[' =>			if(++nlb < 256)				s = s[1:];			else				s[0] = 'X';	# force verifyerrormess()		* =>			verifyerrormess("field/method descriptor");		}	}} j2dtype(jtype: byte): byte{	dtype: byte; 	case int jtype {	'Z' or	'B' or	'C' or	'S' or	'I' =>		dtype = byte DIS_W;	'J' or	'F' or	'D' =>		dtype = byte DIS_L;	'L' or	'[' =>		dtype = byte DIS_P;	}	return dtype;} ## $i operands# addrimm(a: ref Addr, ival: int){	a.mode = byte Aimm;	a.ival = ival;} ## Is an int too big to be an immediate operand?# notimmable(val: int): int{	return val < 0 && ((val >> 29) & 7) != 7 || val > 0 && (val >> 29) != 0;} ## i(fp) and i(mp) operands# addrsind(a: ref Addr, mode: byte, off: int){	a.mode = mode;	a.offset = off;} ## i(j(fp)) and i(j(mp)) operands# addrdind(a: ref Addr, mode: byte, fi: int, si: int){	a.mode = mode;	a.ival = fi;	a.offset = si;} ## Assign a register to a destination operand if not already done so.# dstreg(a: ref Addr, dtype: byte){	if(a.mode == Afp && a.offset == -1)		a.offset = getreg(dtype);} ## Print a string.# pstring(s: string){	slen, c: int; 	slen = len s;	for(i := 0; i < slen; i++) {		c = s[i];		if(c == '\n')			bout.puts("\\n");		else if(c == '\t')			bout.puts("\\t");		else if(c == '"')			bout.puts("\\\"");		else if(c == '\\')			bout.puts("\\\\");		else			bout.putc(c);	}} ## Die.# fatal(msg: string){	print("fatal j2d error: %s\n", msg);	if(bout != nil)		sys->remove(ofile);	reset();	if(fabort) {		j: ref Jinst;		if(j.dst == nil);	# abort	}	raise "fail:fail";	#exit;} ## Bytecode verification.# ## Verify a constant pool index.# verifycpindex(j: ref Jinst, ix: int, CON_bits: int){	if(ix > 0 && ix < class.cp_count && ((1 << int class.cts[ix]) & CON_bits))		return; 	if(j != nil)		verifyerror(j);	else		verifyerrormess("constant pool index");} verifyerror(j: ref Jinst){	fatal("VerifyError: " + jinstconv(j));} verifyerrormess(mess: string){	fatal("VerifyError: " + mess);} badpick(s: string){	fatal("bad pick in " + s);} hex(v, n: int): string{	return sprint("%.*ux", n, v);} ## Size of frame cell of given type.# cellsize := array [int DIS_P + 1] of {	0,		# DIS_X	IBY2WD,		# DIS_W	IBY2LG,		# DIS_L	IBY2WD,		# DIS_P}; ## enable consecutive runs of J2d->init() without having to reload# reset(){	i: int; 	# asm.b	clinitclone = nil; 	# bb.b	roots = nil;	nr = 0;	maxr = 0; 	# datarloc.b	dreloc = nil;	Ipatchtid = 0; 	# desc.b	dlist = nil;	dtail = nil;	id = 0; 	# dis.b	ihead = nil;	itail = nil;	cache = nil;	ncached = 0;	ndatum = 0;	startoff = 0;	lastoff = 0;	lastkind = -1;	lencache = 0;	ibuf = nil;	nibuf = 0; 	# entry.b	pc = -1;	tid = -1; 	# finally.b	finally = nil; 	# frame.b	frameoff = 0;	maxframe = 0;	locals = nil;	nlocals = 0;	tmpslwm = 0;	tmpssz = 0;	tmps = nil; 	# links.b	links = nil;	nlinks = 0;	fcplist = nil; 	# loader.b	pcode = nil;	THISCLASS = nil;	SUPERCLASS = nil; 	# ltreloc.b	doclinitinits = 0;	for(i = 0; i < Hashsize; i++)		lttbl[i] = nil;	thisclass = nil;	nltclasses = 0;	Freloctid = 0;	Ifacetid = 0; 	# main.b	gendis = 1;	fabort = 0;	emitcpool = 0;	verbose = 0;	bout = nil; 	# mdata.b	for(i = 0; i < Hashsize; i++)		htable[i] = nil;	# mpoff should not be zero,	# as zero is reserved for nil ptr	mpoff = IBY2WD;	mplist = nil;	mptail = nil;	llist = nil;	rlist = nil; 	# patch.b	plist = nil; 	# rtreloc.b	for(i = 0; i < Hashsize; i++)		rttbl[i] = nil;	nrtclasses = 0;	RTReloctid = 0; 	# xlate.b	code = nil;	pcdis = 0;	callunrescue = 0;	rtcache = nil;	rtncache = 0;	rtnmax = 0;	ehinst = nil;	trylist = nil;}