2345 lines · 48.5 KB · Brainfuck
RawDownload
maxstack:	int;				# max size of a stack frame called precasttab := array[Tend] of array of ref Type; optabinit(){	ct := array[Tend] of ref Type;	for(i := 0; i < Tend; i++)		precasttab[i] = ct;	precasttab[Tstring] = array[Tend] of { Tbyte => tint, Tfix => treal, };	precasttab[Tbig] = array[Tend] of { Tbyte => tint, Tfix => treal, };	precasttab[Treal] = array[Tend] of { Tbyte => tint, };	precasttab[Tfix] = array[Tend] of { Tbyte => tint, Tstring => treal, Tbig => treal, };	precasttab[Tbyte] = array[Tend] of { Tstring => tint, Tbig => tint, Treal => tint, Tfix => tint, }; 	casttab = array[Tend] of { * => array[Tend] of {* => 0}}; 	casttab[Tint][Tint] = IMOVW;	casttab[Tbig][Tbig] = IMOVL;	casttab[Treal][Treal] = IMOVF;	casttab[Tbyte][Tbyte] = IMOVB;	casttab[Tstring][Tstring] = IMOVP;	casttab[Tfix][Tfix] = ICVTXX;	# never same type 	casttab[Tint][Tbyte] = ICVTWB;	casttab[Tint][Treal] = ICVTWF;	casttab[Tint][Tstring] = ICVTWC;	casttab[Tint][Tfix] = ICVTXX;	casttab[Tbyte][Tint] = ICVTBW;	casttab[Treal][Tint] = ICVTFW;	casttab[Tstring][Tint] = ICVTCW;	casttab[Tfix][Tint] = ICVTXX; 	casttab[Tint][Tbig] = ICVTWL;	casttab[Treal][Tbig] = ICVTFL;	casttab[Tstring][Tbig] = ICVTCL;	casttab[Tbig][Tint] = ICVTLW;	casttab[Tbig][Treal] = ICVTLF;	casttab[Tbig][Tstring] = ICVTLC; 	casttab[Treal][Tstring] = ICVTFC;	casttab[Tstring][Treal] = ICVTCF; 	casttab[Treal][Tfix] = ICVTFX;	casttab[Tfix][Treal] = ICVTXF; 	casttab[Tstring][Tarray] = ICVTCA;	casttab[Tarray][Tstring] = ICVTAC; 	#	# placeholders; fixed in precasttab	#	casttab[Tbyte][Tstring] = 16rff;	casttab[Tstring][Tbyte] = 16rff;	casttab[Tbyte][Treal] = 16rff;	casttab[Treal][Tbyte] = 16rff;	casttab[Tbyte][Tbig] = 16rff;	casttab[Tbig][Tbyte] = 16rff;	casttab[Tfix][Tbyte] = 16rff;	casttab[Tbyte][Tfix] = 16rff;	casttab[Tfix][Tbig] = 16rff;	casttab[Tbig][Tfix] = 16rff;	casttab[Tfix][Tstring] = 16rff;	casttab[Tstring][Tfix] = 16rff;} ## global variable and constant initialization checking#vcom(ids: ref Decl): int{	ok := 1;	for(v := ids; v != nil; v = v.next)		ok &= varcom(v);	for(v = ids; v != nil; v = v.next)		v.init = simplify(v.init);	return ok;} simplify(n: ref Node): ref Node{	if(n == nil)		return nil;	if(debug['F'])		print("simplify %s\n", nodeconv(n));	n = efold(rewrite(n));	if(debug['F'])		print("simplified %s\n", nodeconv(n));	return n;} isfix(n: ref Node): int{	if(n.ty.kind == Tint || n.ty.kind == Tfix){		if(n.op == Ocast)			return n.left.ty.kind == Tint || n.left.ty.kind == Tfix;		return 1;	}	return 0;} ## rewrite an expression to make it easiser to compile,# or give the correct results#rewrite(n: ref Node): ref Node{	v: big;	t: ref Type;	d: ref Decl;	nn: ref Node; 	if(n == nil)		return nil; 	left := n.left;	right := n.right; 	#	# rewrites	#	case n.op{	Oname =>		d = n.decl;		if(d.importid != nil){			left = mkbin(Omdot, dupn(1, n.src, d.eimport), mkdeclname(n.src, d.importid));			left.ty = n.ty;			return rewrite(left);		}		if((t = n.ty).kind == Texception){			if(int t.cons)				fatal("cons in rewrite Oname");			n = mkbin(Oadd, n, mkconst(n.src, big(2*IBY2WD)));			n = mkunary(Oind, n);			n.ty = t;			n.left.ty = n.left.left.ty = tint;			return rewrite(n);		}	Odas =>		n.op = Oas;		return rewrite(n);	Oneg =>		n.left = rewrite(left);		if(n.ty == treal)			break;		left = n.left;		n.right = left;		n.left = mkconst(n.src, big 0);		n.left.ty = n.ty;		n.op = Osub;	Ocomp =>		v = big 0;		v = ~v;		n.right = mkconst(n.src, v);		n.right.ty = n.ty;		n.left = rewrite(left);		n.op = Oxor;	Oinc or	Odec or	Opreinc or	Opredec =>		n.left = rewrite(left);		case n.ty.kind{		Treal =>			n.right = mkrconst(n.src, 1.0);		Tint or		Tbig or		Tbyte or		Tfix =>			n.right = mkconst(n.src, big 1);			n.right.ty = n.ty;		* =>			fatal("can't rewrite inc/dec "+nodeconv(n));		}		if(n.op == Opreinc)			n.op = Oaddas;		else if(n.op == Opredec)			n.op = Osubas;	Oslice =>		if(right.left.op == Onothing)			right.left = mkconst(right.left.src, big 0);		n.left = rewrite(left);		n.right = rewrite(right);	Oindex =>		n.op = Oindx;		n.left = rewrite(left);		n.right = rewrite(right);		n = mkunary(Oind, n);		n.ty = n.left.ty;		n.left.ty = tint;	Oload =>		n.right = mkn(Oname, nil, nil);		n.right.src = n.left.src;		n.right.decl = n.ty.tof.decl;		n.right.ty = n.ty;		n.left = rewrite(left);	Ocast =>		if(left.ty.kind == Texception){			n = rewrite(left);			break;		}		n.op = Ocast;		t = precasttab[left.ty.kind][n.ty.kind];		if(t != nil){			n.left = mkunary(Ocast, left);			n.left.ty = t;			return rewrite(n);		}		n.left = rewrite(left);	Oraise =>		if(left.ty == tstring)			;		else if(left.ty.cons == byte 0)			break;		else if(left.op != Ocall || left.left.ty.kind == Tfn){			left = mkunary(Ocall, left);			left.ty = left.left.ty;		}		n.left = rewrite(left);	Ocall =>		t = left.ty;		if(t.kind == Tref)			t = t.tof;		if(t.kind == Tfn){			if(left.ty.kind == Tref){	# call by function reference				n.left = mkunary(Oind, left);				n.left.ty = t;				return rewrite(n);			}			d = nil;			if(left.op == Oname)				d = left.decl;			else if(left.op == Omdot && left.right.op == Odot)				d = left.right.right.decl;			else if(left.op == Omdot || left.op == Odot)				d = left.right.decl;			else if(left.op != Oind)				fatal("cannot deal with call " + nodeconv(n) + " in rewrite");			if(ispoly(d))				addfnptrs(d, 0);			n.left = rewrite(left);			if(right != nil)				n.right = rewrite(right);			if(d != nil && int d.inline == 1)				n = simplify(inline(n));			break;		}		case n.ty.kind{		Tref =>			n = mkunary(Oref, n);			n.ty = n.left.ty;			n.left.ty = n.left.ty.tof;			n.left.left.ty = n.left.ty;			return rewrite(n);		Tadt =>			n.op = Otuple;			n.right = nil;			if(n.ty.tags != nil){				n.left = nn = mkunary(Oseq, mkconst(n.src, big left.right.decl.tag));				if(right != nil){					nn.right = right;					nn.src.stop = right.src.stop;				}				n.ty = left.right.decl.ty.tof;			}else				n.left = right;			return rewrite(n);		Tadtpick =>			n.op = Otuple;			n.right = nil;			n.left = nn = mkunary(Oseq, mkconst(n.src, big left.right.decl.tag));			if(right != nil){				nn.right = right;				nn.src.stop = right.src.stop;			}			n.ty = left.right.decl.ty.tof;			return rewrite(n);		Texception =>			if(n.ty.cons == byte 0)				return n.left;			if(left.op == Omdot){				left.right.ty = left.ty;				left = left.right;			}			n.op = Otuple;			n.right = nil;			n.left = nn = mkunary(Oseq, left.decl.init);			nn.right = mkunary(Oseq, mkconst(n.src, big 0));			nn.right.right = right;			n.ty = mkexbasetype(n.ty);			n = mkunary(Oref, n);			n.ty = internaltype(mktype(n.src.start, n.src.stop, Tref, t, nil));			return rewrite(n);		* =>			fatal("can't deal with "+nodeconv(n)+" in rewrite/Ocall");		}	Omdot =>		#		# what about side effects from left?		#		d = right.decl;		case d.store{		Dfn =>			n.left = rewrite(left);			if(right.op == Odot){				n.right = dupn(1, left.src, right.right);				n.right.ty = d.ty;			}		Dconst or		Dtag or		Dtype =>			# handled by fold			return n;		Dglobal =>			right.op = Oconst;			right.c = ref Const(big d.offset, 0.);			right.ty = tint; 			n.left = left = mkunary(Oind, left);			left.ty = tint;			n.op = Oadd;			n = mkunary(Oind, n);			n.ty = n.left.ty;			n.left.ty = tint;			n.left = rewrite(n.left);			return n;		Darg =>			return n;		* =>			fatal("can't deal with "+nodeconv(n)+" in rewrite/Omdot");		}	Odot =>		#		# what about side effects from left?		#		d = right.decl;		case d.store{		Dfn =>			if(right.left != nil){				n = mkbin(Omdot, dupn(1, left.src, right.left), right);				right.left = nil;				n.ty = d.ty;				return rewrite(n);			}			if(left.ty.kind == Tpoly){				n = mkbin(Omdot, mkdeclname(left.src, d.link), mkdeclname(left.src, d.link.next));				n.ty = d.ty;				return rewrite(n);			}			n.op = Oname;			n.decl = d;			n.right = nil;			n.left = nil;			return n;		Dconst or		Dtag or		Dtype =>			# handled by fold			return n;		}		if(istuple(left))			return n;	# handled by fold		right.op = Oconst;		right.c = ref Const(big d.offset, 0.);		right.ty = tint; 		if(left.ty.kind != Tref){			n.left = mkunary(Oadr, left);			n.left.ty = tint;		}		n.op = Oadd;		n = mkunary(Oind, n);		n.ty = n.left.ty;		n.left.ty = tint;		n.left = rewrite(n.left);		return n;	Oadr =>		left = rewrite(left);		n.left = left;		if(left.op == Oind)			return left.left;	Otagof =>		if(n.decl == nil){			n.op = Oind;			return rewrite(n);		}		return n;	Omul or	Odiv =>		left = n.left = rewrite(left);		right = n.right = rewrite(right);		if(n.ty.kind == Tfix && isfix(left) && isfix(right)){			if(left.op == Ocast && tequal(left.ty, n.ty))				n.left = left.left;			if(right.op == Ocast && tequal(right.ty, n.ty))				n.right = right.left;		}	Oself =>		if(newfnptr)			return n;		if(selfdecl == nil){			d = selfdecl = mkids(n.src, enter(".self", 5), tany, nil);			installids(Dglobal, d);			d.refs++;		}		nn = mkn(Oload, nil, nil);		nn.src = n.src;		nn.left = mksconst(n.src, enterstring("$self"));		nn.ty = impdecl.ty;		usetype(nn.ty);		usetype(nn.ty.tof);		nn = rewrite(nn);		nn.op = Oself;		return nn;	Ofnptr =>		if(n.flags == byte 0){			# module			if(left == nil)				left = mkn(Oself, nil, nil);			return rewrite(left);		}		right.flags = n.flags;		n = right;		d = n.decl;		if(int n.flags == FNPTR2){			if(left != nil && left.op != Oname)				fatal("not Oname for addiface");			if(left == nil){				addiface(nil, d);				if(newfnptr)					n.flags |= byte FNPTRN;			}			else				addiface(left.decl, d);			n.ty = tint;			return n;		}		if(int n.flags == FNPTRA){			n = mkdeclname(n.src, d.link);			n.ty = tany;			return n;		}		if(int n.flags == (FNPTRA|FNPTR2)){			n = mkdeclname(n.src, d.link.next);			n.ty = tint;			return n;		}	Ochan =>		if(left == nil)			left = n.left = mkconst(n.src, big 0);		n.left = rewrite(left);	* =>		n.left = rewrite(left);		n.right = rewrite(right);	} 	return n;} ## label a node with sethi-ullman numbers and addressablity# genaddr interprets addable to generate operands,# so a change here mandates a change there.## addressable:#	const			Rconst	$value		 may also be Roff or Rdesc or Rnoff#	Asmall(local)		Rreg	value(FP)#	Asmall(global)		Rmreg	value(MP)#	ind(Rareg)		Rreg	value(FP)#	ind(Ramreg)		Rmreg	value(MP)#	ind(Rreg)		Radr	*value(FP)#	ind(Rmreg)		Rmadr	*value(MP)#	ind(Raadr)		Radr	value(value(FP))#	ind(Ramadr)		Rmadr	value(value(MP))## almost addressable:#	adr(Rreg)		Rareg#	adr(Rmreg)		Ramreg#	add(const, Rareg)	Rareg#	add(const, Ramreg)	Ramreg#	add(const, Rreg)	Raadr#	add(const, Rmreg)	Ramadr#	add(const, Raadr)	Raadr#	add(const, Ramadr)	Ramadr#	adr(Radr)		Raadr#	adr(Rmadr)		Ramadr## strangely addressable:#	fn			Rpc#	mdot(module,exp)	Rmpc#sumark(n: ref Node): ref Node{	if(n == nil)		return nil; 	n.temps = byte 0;	n.addable = Rcant; 	left := n.left;

Lines 1–500 of 2345.