// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "go.h" #include "gen.h" Prog* gbranch(int op, Node *t) { Prog *p; p = prog(op); p->addr.type = ABRANCH; p->pt = conv2pt(t); return p; } Prog* gopcode(int op, int pt, Node *n) { Prog *p; p = prog(op); p->pt = pt; p->addr.node = n; if(n == N) { p->addr.type = ANONE; return p; } if(n->op == OTYPE) { p->pt1 = conv2pt(n); p->addr.type = ANONE; return p; } p->addr.type = ANODE; // p->param = n->param; return p; } Prog* gopcodet(int op, Node *t, Node *n) { return gopcode(op, conv2pt(t), n); } void gaddoffset(Node *n) { Prog *p; if(n == N || n->op != ONAME || n->sym == S) goto bad; p = gopcode(PADDO, PTADDR, n); return; bad: fatal("gaddoffset: %N", n); } void gconv(int t1, int t2) { Prog *p; p = gopcode(PCONV, t1, N); p->pt1 = t2; } int conv2pt(Node *t) { if(t == N) return PTxxx; switch(t->etype) { case TPTR: t = t->type; if(t == N) return PTERROR; switch(t->etype) { case PTSTRING: case PTCHAN: case PTMAP: return t->etype; } return TPTR; } return t->etype; } void patch(Prog *p, Prog *to) { if(p->addr.type != ABRANCH) yyerror("patch: not a branch"); p->addr.branch = to; } Prog* prog(int as) { Prog *p; p = pc; pc = mal(sizeof(*pc)); pc->op = PEND; pc->addr.type = ANONE; pc->loc = p->loc+1; p->op = as; p->lineno = dynlineno; p->link = pc; return p; } void proglist(void) { Prog *p; print("--- prog list ---\n"); for(p=firstpc; p!=P; p=p->link) print("%P\n", p); } char* ptnames[] = { [PTxxx] = "", [PTINT8] = "I8", [PTUINT8] = "U8", [PTINT16] = "I16", [PTUINT16] = "U16", [PTINT32] = "I32", [PTUINT32] = "U32", [PTINT64] = "I64", [PTUINT64] = "U64", [PTFLOAT32] = "F32", [PTFLOAT64] = "F64", [PTFLOAT80] = "F80", [PTBOOL] = "B", [PTPTR] = "P", [PTADDR] = "A", [PTINTER] = "I", [PTNIL] = "N", [PTSTRUCT] = "S", [PTSTRING] = "Z", [PTCHAN] = "C", [PTMAP] = "M", [PTERROR] = "?", }; int Xconv(Fmt *fp) { char buf[100]; int pt; pt = va_arg(fp->args, int); if(pt < 0 || pt >= nelem(ptnames) || ptnames[pt] == nil) { snprint(buf, sizeof(buf), "PT(%d)", pt); return fmtstrcpy(fp, buf); } return fmtstrcpy(fp, ptnames[pt]); } int Qconv(Fmt *fp) { char buf[100]; int pt; pt = va_arg(fp->args, int); if(pt == PTADDR) pt = PTPTR; snprint(buf, sizeof(buf), "_T_%X", pt); return fmtstrcpy(fp, buf); } int Rconv(Fmt *fp) { char buf[100]; int pt; pt = va_arg(fp->args, int); if(pt == PTADDR) snprint(buf, sizeof(buf), "_R_%X", pt); else snprint(buf, sizeof(buf), "_U._R_%X", pt); return fmtstrcpy(fp, buf); } /* s%[ ]*%%g s%(\/\*.*)*%%g s%,%\n%g s%\n+%\n%g s%(=0)*%%g s%^P(.+)% [P\1] = "\1",%g s%^ ........*\] =%&~%g s% =~%=%g */ static char* pnames[] = { [PXXX] = "XXX", [PERROR] = "ERROR", [PPANIC] = "PANIC", [PPRINT] = "PRINT", [PGOTO] = "GOTO", [PGOTOX] = "GOTOX", [PCMP] = "CMP", [PNEW] = "NEW", [PLEN] = "LEN", [PTEST] = "TEST", [PCALL1] = "CALL1", [PCALL2] = "CALL2", [PCALLI2] = "CALLI2", [PCALLM2] = "CALLM2", [PCALLF2] = "CALLF2", [PCALL3] = "CALL3", [PRETURN] = "RETURN", [PBEQ] = "BEQ", [PBNE] = "BNE", [PBLT] = "BLT", [PBLE] = "BLE", [PBGE] = "BGE", [PBGT] = "BGT", [PBTRUE] = "BTRUE", [PBFALSE] = "BFALSE", [PLOAD] = "LOAD", [PLOADI] = "LOADI", [PSTORE] = "STORE", [PSTOREI] = "STOREI", [PSTOREZ] = "STOREZ", [PSTOREZI] = "STOREZI", [PCONV] = "CONV", [PADDR] = "ADDR", [PADDO] = "ADDO", [PINDEX] = "INDEX", [PINDEXZ] = "INDEXZ", [PCAT] = "CAT", [PADD] = "ADD", [PSUB] = "SUB", [PSLICE] = "SLICE", [PMUL] = "MUL", [PDIV] = "DIV", [PLSH] = "LSH", [PRSH] = "RSH", [PMOD] = "MOD", [PMINUS] = "MINUS", [PCOM] = "COM", [PAND] = "AND", [POR] = "OR", [PXOR] = "XOR", [PEND] = "END", }; int Aconv(Fmt *fp) { char buf[100], buf1[100]; Prog *p; int o; p = va_arg(fp->args, Prog*); if(p == P) { snprint(buf, sizeof(buf), "
");
goto ret;
}
o = p->op;
if(o < 0 || o >= nelem(pnames) || pnames[o] == nil)
snprint(buf, sizeof(buf), "(A%d)", o);
else
snprint(buf, sizeof(buf), "%s", pnames[o]);
o = p->pt;
if(o != PTxxx) {
snprint(buf1, sizeof(buf1), "-%X", o);
strncat(buf, buf1, sizeof(buf));
}
o = p->pt1;
if(o != PTxxx) {
snprint(buf1, sizeof(buf1), "-%X", o);
strncat(buf, buf1, sizeof(buf));
}
ret:
return fmtstrcpy(fp, buf);
}
int
Pconv(Fmt *fp)
{
char buf[500], buf1[500];
Prog *p;
p = va_arg(fp->args, Prog*);
snprint(buf1, sizeof(buf1), "%4ld %4ld %-9A", p->loc, p->lineno, p);
switch(p->addr.type) {
default:
snprint(buf, sizeof(buf), "?%d", p->addr.type);
break;
case ANONE:
goto out;
case ANODE:
snprint(buf, sizeof(buf), "%N", p->addr.node);
break;
case ABRANCH:
if(p->addr.branch == P) {
snprint(buf, sizeof(buf), "