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. Load more
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;