summaryrefslogtreecommitdiff
path: root/src/old/c/obj.c
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2008-06-04 14:46:07 -0700
committerRob Pike <r@golang.org>2008-06-04 14:46:07 -0700
commit5cf1e37b96825023b2da8de9be3a07d1987bb306 (patch)
treefda9e615c7d6ddb748cee567027fae05ba9215ae /src/old/c/obj.c
parent0a2697043d69739b27b6ba872b2092a4c2bb61a8 (diff)
downloadgolang-5cf1e37b96825023b2da8de9be3a07d1987bb306.tar.gz
move old code into 'old' directory
add src/test dir SVN=121166
Diffstat (limited to 'src/old/c/obj.c')
-rw-r--r--src/old/c/obj.c1556
1 files changed, 1556 insertions, 0 deletions
diff --git a/src/old/c/obj.c b/src/old/c/obj.c
new file mode 100644
index 000000000..f44a0f083
--- /dev/null
+++ b/src/old/c/obj.c
@@ -0,0 +1,1556 @@
+// 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"
+
+static Prog* firstp;
+static Prog* lastp;
+static int typeexpand;
+
+void
+dumpobj(void)
+{
+ Plist *pl;
+ Prog *p;
+ long lno;
+
+ Bprint(bout, "\n\n/*\n");
+ Bprint(bout, " * automatic code generated from\n");
+ Bprint(bout, " * %s in package \"%s\"\n", curio.infile, package);
+ dumpexport();
+ Bprint(bout, " */\n", curio.infile, package);
+ Bprint(bout, "#include \"gort.h\"\n");
+
+ // put out external variables and types
+ doframe(externdcl, "external");
+ dumpmethods();
+
+ // put out signatures
+ dumpsignatures();
+
+ // put out functions
+ for(pl=plist; pl!=nil; pl=pl->link) {
+ /* print out the function header */
+ dumpfunct(pl);
+
+ /* clear the marks */
+ for(p=pl->firstpc; p!=nil; p=p->link)
+ p->mark = 0;
+
+ /* relinearize the object code */
+ firstp = mal(sizeof(*firstp));
+ lastp = firstp;
+ follow(pl->firstpc);
+ lastp->link = P;
+ pl->firstpc = firstp->link;
+
+ /* clear the marks - relabel the locations */
+ for(p=pl->firstpc; p!=nil; p=p->link)
+ p->mark = 0;
+
+ /* mark the labels */
+ for(p=pl->firstpc; p!=nil; p=p->link) {
+ if(p->addr.branch != P)
+ p->addr.branch->mark = 1;
+ }
+
+ /* interpret the instructions */
+ lno = dynlineno;
+ for(p=pl->firstpc; p!=nil; p=p->link) {
+ dynlineno = p->lineno;
+ dynloc = p->loc;
+ obj(p);
+ }
+ dynlineno = lno;
+ Bprint(bout, "}\n");
+ }
+}
+
+void
+obj1(Prog *p)
+{
+ Node *n;
+ static long uloc, olino;
+
+ Bprint(bout, "\n\t// %P\n", p);
+ if(p->mark)
+ Bprint(bout, "_L%ld:\n", p->loc);
+
+ uloc++;
+ if(p->lineno != 0)
+ olino = p->lineno;
+ Bprint(bout, "\tgotrace(%ld, %ld);\n", uloc, olino);
+
+ switch(p->op) {
+ default:
+ warn("obj: unknown opcode %A", p);
+ Bprint(bout, "\tprintf(\"unknown line %ld-%ld: %A\\n\");\n",
+ dynloc, dynlineno, p);
+
+ case PPANIC:
+ Bprint(bout, "\tprintf(\"panic line %ld\\n\");\n", dynlineno);
+ Bprint(bout, "\tgoexit(1);\n");
+ break;
+
+ case PPRINT:
+ Bprint(bout, "\tprint%s(%R);\n", getfmt(p->pt), p->pt);
+ break;
+
+ case PGOTO:
+ Bprint(bout, "\tgoto %D;\n", p);
+ break;
+
+ case PGOTOX:
+ yyerror("label not declared: %S", p->addr.node->left->sym);
+ break;
+
+ case PCMP:
+ if(p->pt == PTSTRING)
+ goto pcmpz;
+
+ switch(p->link->op) {
+ case PBEQ:
+ Bprint(bout, "\tif(%R == %D) {\n", p->pt, p);
+ break;
+ case PBNE:
+ Bprint(bout, "\tif(%R != %D) {\n", p->pt, p);
+ break;
+ case PBLT:
+ Bprint(bout, "\tif(%R < %D) {\n", p->pt, p);
+ break;
+ case PBLE:
+ Bprint(bout, "\tif(%R <= %D) {\n", p->pt, p);
+ break;
+ case PBGE:
+ Bprint(bout, "\tif(%R >= %D) {\n", p->pt, p);
+ break;
+ case PBGT:
+ Bprint(bout, "\tif(%R > %D) {\n", p->pt, p);
+ break;
+ }
+ break;
+
+ pcmpz:
+ Bprint(bout, "\tif(cmpZ(%D) ", p);
+ switch(p->link->op) {
+ case PBEQ:
+ Bprint(bout, "== 0) {\n");
+ break;
+ case PBNE:
+ Bprint(bout, "!= 0) {\n");
+ break;
+ case PBLT:
+ Bprint(bout, "< 0) {\n");
+ break;
+ case PBLE:
+ Bprint(bout, "<= 0) {\n");
+ break;
+ case PBGE:
+ Bprint(bout, ">= 0) {\n");
+ break;
+ case PBGT:
+ Bprint(bout, "> 0) {\n");
+ break;
+ }
+ break;
+
+ case PTEST:
+ switch(p->link->op) {
+ case PBTRUE:
+ Bprint(bout, "\tif(%D != 0) {\n", p);
+ break;
+ case PBFALSE:
+ Bprint(bout, "\tif(%D == 0) {\n", p);
+ break;
+ }
+ break;
+
+ case PBEQ:
+ case PBNE:
+ case PBLT:
+ case PBLE:
+ case PBGE:
+ case PBGT:
+ case PBTRUE:
+ case PBFALSE:
+ Bprint(bout, "\t\tgoto %D; }\n", p);
+ break;
+
+ case PLEN:
+ Bprint(bout, "\t%R = %D->len;\n", PTINT32, p);
+ break;
+
+ case PNEW:
+ if(p->addr.type != ANODE)
+ goto bad;
+ n = p->addr.node;
+ n = n->type;
+ n = n->type;
+ if(n == N || n->op != OTYPE)
+ goto bad;
+ Bprint(bout, "\t%R = gomal(sizeof(%C%lC));\n", p->pt, n, n);
+ break;
+
+ case PLOAD:
+ if(p->pt == PTPTR || p->pt == PTADDR) {
+ Bprint(bout, "\t%R = (%Q)%D;\n", p->pt, PTPTR, p);
+ break;
+ }
+ Bprint(bout, "\t%R = %D;\n", p->pt, p);
+ break;
+
+ case PLOADI: // R/D = *(A)
+ Bprint(bout, "\t%D = *(%Q*)%R;\n", p, p->pt, PTADDR);
+ break;
+
+ case PSTORE:
+ if(p->pt == PTPTR || p->pt == PTADDR) {
+ if(p->addr.type != ANODE)
+ goto bad;
+ n = p->addr.node;
+ if(n == N || n->type == N)
+ goto bad;
+ Bprint(bout, "\t%D = (%C)%R;\n", p, n->type, p->pt);
+ break;
+ }
+ Bprint(bout, "\t%D = %R;\n", p, p->pt);
+ break;
+
+ case PSTOREI: // *(A) = R/D
+ Bprint(bout, "\t*(%Q*)%R = %D;\n", p->pt, PTADDR, p);
+ break;
+
+ case PSTOREZ:
+ switch(p->pt) {
+ default:
+ Bprint(bout, "\t%D = 0;\n", p);
+ break;
+
+ case PTARRAY:
+ case PTSTRUCT:
+ Bprint(bout, "\tmemset(&%D, 0, sizeof(%D));\n", p, p);
+ break;
+
+ case PTINTER:
+ Bprint(bout, "\t%D.s = 0; %D.m = 0;\n", p, p);
+ break;
+
+ case PTSTRING:
+ Bprint(bout, "\t%D = &nilstring;\n", p);
+ break;
+ }
+ break;
+
+ case PSTOREZI:
+ switch(p->pt) {
+ default:
+ Bprint(bout, "\t*(%Q*)%R = 0;\n", p->pt, PTADDR);
+ break;
+
+ case PTARRAY:
+ case PTSTRUCT:
+ Bprint(bout, "\tmemset((%Q*)%R, 0, sizeof((%Q*)%R));\n", p->pt, PTADDR, p->pt, PTADDR);
+ break;
+
+ case PTINTER:
+ Bprint(bout, "\t((%Q*)%R)->s = 0; ((%Q*)%R)->m = 0;\n", p->pt, PTADDR, p->pt, PTADDR);
+ break;
+
+ case PTSTRING:
+ Bprint(bout, "\t(%Q*)%R = &nilstring;\n", p->pt, PTADDR);
+ break;
+ }
+ break;
+
+ case PCONV:
+ doconv(p);
+ break;
+
+ case PADDR:
+ Bprint(bout, "\t%R = (%Q)&%D;\n", p->pt, p->pt, p);
+ break;
+
+ case PADDO:
+ if(p->addr.type != ANODE)
+ goto bad;
+ n = p->addr.node;
+ if(n == N || n->op != ONAME || n->sym == S)
+ goto bad;
+ if(n->uberstruct == N || n->uberstruct->etype != TSTRUCT)
+ goto bad;
+
+ Bprint(bout, "\t%R = (%Q)((char*)%R + offsetof(_T_%ld, %s));\n",
+ p->pt, PTADDR, p->pt,
+// n->uberstruct->nname->sym->package,
+ n->uberstruct->vargen, n->sym->name);
+ break;
+
+ case PINDEXZ:
+ Bprint(bout, "\t%R = %D->string[%R];\n",
+ PTUINT8, p, p->pt);
+ break;
+
+ case PINDEX:
+ if(p->addr.type != ANODE)
+ goto bad;
+ n = p->addr.node;
+ Bprint(bout, "\t%R += (%R)*sizeof(%C);\n",
+ PTADDR, p->pt, n->type);
+ break;
+
+ case PSLICE:
+ if(p->addr.type != ANODE)
+ goto bad;
+ n = p->addr.node;
+ Bprint(bout, "\tsliceZ(%R, %D);\n", p->pt, p);
+ break;
+
+ case PCAT:
+ Bprint(bout, "\tcatZ(%D);\n", p);
+ break;
+
+ case PADD:
+ Bprint(bout, "\t%R += %D;\n", p->pt, p);
+ break;
+
+ case PSUB:
+ Bprint(bout, "\t%R -= %D;\n", p->pt, p);
+ break;
+
+ case PMUL:
+ Bprint(bout, "\t%R *= %D;\n", p->pt, p);
+ break;
+
+ case PDIV:
+ Bprint(bout, "\t%R /= %D;\n", p->pt, p);
+ break;
+
+ case PLSH:
+ Bprint(bout, "\t%R <<= %D;\n", p->pt, p);
+ break;
+
+ case PRSH:
+ Bprint(bout, "\t%R >>= %D;\n", p->pt, p);
+ break;
+
+ case PMOD:
+ Bprint(bout, "\t%R %%= %D;\n", p->pt, p);
+ break;
+
+ case PAND:
+ Bprint(bout, "\t%R &= %D;\n", p->pt, p);
+ break;
+
+ case POR:
+ Bprint(bout, "\t%R |= %D;\n", p->pt, p);
+ break;
+
+ case PXOR:
+ Bprint(bout, "\t%R ^= %D;\n", p->pt, p);
+ break;
+
+ case PMINUS:
+ Bprint(bout, "\t%R = -%R;\n", p->pt, p->pt);
+ break;
+
+ case PCOM:
+ Bprint(bout, "\t%R = ~%R;\n", p->pt, p->pt);
+ break;
+
+ case PRETURN:
+ Bprint(bout, "\treturn;\n");
+ break;
+
+ case PCALL1: // process the arguments
+ docall1(p);
+ break;
+
+ case PCALL2: // call the normal function
+ docall2(p);
+ break;
+
+ case PCALLI2: // call the indirect function
+ docalli2(p);
+ break;
+
+ case PCALLM2: // call the method function
+ docallm2(p);
+ break;
+
+ case PCALLF2: // call the interface method function
+ docallf2(p);
+ break;
+
+ case PCALL3: // process the return
+ docall3(p);
+ break;
+
+ case PEND:
+ Bprint(bout, "\treturn;\n");
+ break;
+ }
+ return;
+
+bad:
+ print("bad code generation on\n\t// %P\n", p);
+}
+
+
+void
+follow(Prog *p)
+{
+ Prog *q;
+ int i, op;
+
+loop:
+ if(p == P)
+ return;
+
+ if(p->op == PGOTO) {
+ q = p->addr.branch;
+ if(q != P) {
+ p->mark = 1;
+ p = q;
+ if(p->mark == 0)
+ goto loop;
+ }
+ }
+
+ if(p->mark) {
+ /* copy up to 4 instructions to avoid branch */
+ for(i=0, q=p; i<4; i++, q=q->link) {
+ if(q == P)
+ break;
+ if(q == lastp)
+ break;
+ if(q->op == PGOTO)
+ break;
+ if(q->addr.branch == P)
+ continue;
+ if(q->addr.branch->mark)
+ continue;
+ if(q->op == PCALL1)
+ continue;
+
+ // we found an invertable now copy
+// for(;;) {
+// q = copyp(p);
+// p = p->link;
+// q->mark = 1;
+// lastp->link = q;
+// lastp = q;
+// if(q->op != a || q->addr.branch == P || q->addr.branch->mark)
+// continue;
+//
+// q->op = relinv(q->op);
+// p = q->addr.branch;
+// q->addr.branch = q->link;
+// q->link = p;
+// follow(q->link);
+// p = q->link;
+// if(p->mark)
+// return;
+// goto loop;
+// }
+ }
+
+ q = mal(sizeof(*q));
+ q->op = PGOTO;
+ q->lineno = p->lineno;
+ q->addr.type = ABRANCH;
+ q->addr.branch = gotochain(p);
+ p = q;
+ }
+
+ p->mark = 1;
+ p->loc = lastp->loc+1;
+ lastp->link = p;
+ lastp = p;
+
+ op = p->op;
+ if(op == PGOTO || op == PRETURN || op == OEND)
+ return;
+
+ if(op == PCALL1 || p->addr.branch == P) {
+ p = p->link;
+ goto loop;
+ }
+
+ q = gotochain(p->link);
+ if(q != P && q->mark) {
+ p->op = brcom(op);
+ p->link = p->addr.branch;
+ p->addr.branch = q;
+ }
+ follow(p->link);
+ q = gotochain(p->addr.branch);
+ p->addr.branch = q;
+ if(q != P && q->mark)
+ return;
+
+ p = q;
+ goto loop;
+}
+
+void
+obj(Prog *p)
+{
+ Node *n;
+ String *s;
+ long i;
+
+ if(p->addr.type != ANODE)
+ goto out;
+ n = p->addr.node;
+ if(n == N || n->op != OLITERAL)
+ goto out;
+ if(p->pt != PTSTRING)
+ goto out;
+
+ s = n->val.sval;
+ Bprint(bout, "\t{ static struct {_T_U32 l;_T_U8 s[%d]; } slit = { %d", s->len, s->len);
+ for(i=0; i<s->len; i++) {
+ if(i%16 == 0)
+ Bprint(bout, "\n\t\t");
+ Bprint(bout, ",%d", s->s[i]);
+ }
+ Bprint(bout, " };\n");
+
+ obj1(p);
+ Bprint(bout, "\t}\n");
+ return;
+
+out:
+ obj1(p);
+}
+
+Prog*
+gotochain(Prog *p)
+{
+ int i;
+
+ for(i=0; i<20; i++) {
+ if(p == P || p->op != PGOTO)
+ return p;
+ p = p->addr.branch;
+ }
+ return P;
+}
+
+/*
+ * print a C type
+ */
+int
+Cconv(Fmt *fp)
+{
+ char buf[1000], buf1[100];
+ Node *t, *f, *n;
+ Iter it;
+ int pt;
+ long v1, v2;
+
+ t = va_arg(fp->args, Node*);
+ if(t == N)
+ return fmtstrcpy(fp, "<C>");
+
+ t->recur++;
+ if(t->op != OTYPE) {
+ snprint(buf, sizeof(buf), "C-%O", t->op);
+ goto out;
+ }
+ if(t->recur > 5) {
+ snprint(buf, sizeof(buf), "C-%E ...", t->etype);
+ goto out;
+ }
+
+ // post-name format
+ if(fp->flags & FmtLong) {
+ strcpy(buf, "");
+ switch(t->etype) {
+ default:
+ break;
+ case TARRAY:
+ snprint(buf, sizeof(buf), "[%ld]", t->bound);
+ break;
+ case TFUNC:
+ if(t->thistuple > 0) {
+ f = *getthis(t);
+ v1 = 9999;
+ v2 = 9999;
+ if(f != N) {
+ v1 = f->vargen;
+ if(f->nname != N)
+ v2 = f->nname->vargen;
+ }
+ snprint(buf1, sizeof(buf1), "(_T_%ld* _V_%ld",
+ v1, v2);
+ strncat(buf, buf1, sizeof(buf));
+ } else
+ strncat(buf, "(void* _dummythis", sizeof(buf));
+
+ if(t->outtuple > 0) {
+ f = *getoutarg(t);
+ v1 = 9999;
+ v2 = 9999;
+ if(f != N) {
+ v1 = f->vargen;
+ if(f->nname != N)
+ v2 = f->nname->vargen;
+ }
+ snprint(buf1, sizeof(buf1), ", _T_%ld* _V_%ld",
+ v1, v2);
+ strncat(buf, buf1, sizeof(buf));
+ } else
+ strncat(buf, ", void* _dummyout", sizeof(buf));
+
+ if(t->intuple > 0) {
+ f = *getinarg(t);
+ v1 = 9999;
+ v2 = 9999;
+ if(f != N) {
+ v1 = f->vargen;
+ if(f->nname != N)
+ v2 = f->nname->vargen;
+ }
+ snprint(buf1, sizeof(buf1), ", _T_%ld* _V_%ld)",
+ v1, v2);
+ strncat(buf, buf1, sizeof(buf));
+ } else
+ strncat(buf, ", void* _dummyin)", sizeof(buf));
+ break;
+ }
+ goto out;
+ }
+
+ if(t->vargen != 0 && !typeexpand) {
+ if(t->etype == TFUNC) {
+ strcpy(buf, "void");
+ goto out;
+ }
+ snprint(buf, sizeof(buf), "_T_%ld", t->vargen);
+ goto out;
+ }
+
+ switch(t->etype) {
+ default:
+ pt = conv2pt(t);
+ snprint(buf, sizeof(buf), "%Q", pt);
+ break;
+
+ case TSTRUCT:
+ if(fp->flags & FmtShort) {
+ strcpy(buf, "{");
+ } else {
+ if(t->vargen != 0) {
+ snprint(buf, sizeof(buf), "_T_%ld", t->vargen);
+ goto out;
+ }
+ strcpy(buf, "struct{");
+ }
+
+ f = structfirst(&it, &t);
+ while(f != N) {
+ n = f->type;
+ if(n->etype == TFUNC)
+ goto next;
+ if(f->sym == S)
+ snprint(buf1, sizeof(buf1), "%C;", n);
+ else
+ snprint(buf1, sizeof(buf1), "%C %s;", n, f->sym->name);
+ strncat(buf, buf1, sizeof(buf));
+ next:
+ f = structnext(&it);
+ }
+ strncat(buf, "}", sizeof(buf));
+ break;
+
+ case TPTR:
+ if(isptrto(t, TSTRING)) {
+ snprint(buf, sizeof(buf), "%C", t->type);
+ break;
+ }
+ snprint(buf, sizeof(buf), "%C*", t->type);
+ break;
+
+ case TARRAY:
+ snprint(buf, sizeof(buf), "%C", t->type);
+ break;
+
+ case TFUNC:
+ strcpy(buf, "void");
+ break;
+ }
+
+out:
+ t->recur--;
+ return fmtstrcpy(fp, buf);
+}
+
+/*
+ * print Prog operand
+ */
+int
+Dconv(Fmt *fp)
+{
+ char buf[500];
+ Prog *p;
+ Node *n;
+
+ if(fp->flags & FmtLong) {
+ p = nil;
+ n = va_arg(fp->args, Node*);
+ goto prnode;
+ }
+ p = va_arg(fp->args, Prog*);
+
+ switch(p->addr.type) {
+ default:
+ snprint(buf, sizeof(buf), "addr.type=%d", p->addr.type);
+ break;
+
+ case ANONE:
+ snprint(buf, sizeof(buf), "%R", p->pt);
+ break;
+
+ case ANODE:
+ n = p->addr.node;
+ goto prnode;
+
+ case ABRANCH:
+ p = p->addr.branch;
+ if(p == P) {
+ snprint(buf, sizeof(buf), "addr.branch=nil");
+ break;
+ }
+ snprint(buf, sizeof(buf), "_L%ld", p->loc);
+ break;
+ }
+ goto out;
+
+prnode:
+ if(n == N) {
+ snprint(buf, sizeof(buf), "addr.node=nil");
+ goto out;
+ }
+ switch(n->op) {
+ default:
+ snprint(buf, sizeof(buf), "%N", p->addr.node);
+ break;
+
+ case ONAME:
+ if(n->vargen != 0) {
+ snprint(buf, sizeof(buf), "_V_%ld", n->vargen);
+ break;
+ }
+ snprint(buf, sizeof(buf), "%s_%s", n->sym->opackage, n->sym->name);
+ break;
+
+ case OLITERAL:
+ switch(p->pt) {
+ badlit:
+ default:
+ snprint(buf, sizeof(buf), "BADLIT-%d pt-%d", p->pt, n->val.ctype);
+ break;
+ case PTINT8:
+ case PTINT16:
+ case PTINT32:
+ case PTUINT8:
+ case PTUINT16:
+ case PTUINT32:
+ switch(n->val.ctype) {
+ default:
+ goto badlit;
+ case CTINT:
+ case CTSINT:
+ case CTUINT:
+ if(n->val.vval < 0)
+ snprint(buf, sizeof(buf), "-0x%llux", -n->val.vval);
+ else
+ snprint(buf, sizeof(buf), "0x%llux", n->val.vval);
+ break;
+ }
+ break;
+ case PTINT64:
+ case PTUINT64:
+ switch(n->val.ctype) {
+ default:
+ goto badlit;
+ case CTINT:
+ case CTSINT:
+ case CTUINT:
+ snprint(buf, sizeof(buf), "0x%lluxll", n->val.vval);
+ break;
+ }
+ break;
+ case PTFLOAT32:
+ case PTFLOAT64:
+ case PTFLOAT80:
+ switch(n->val.ctype) {
+ default:
+ goto badlit;
+ case CTFLT:
+ snprint(buf, sizeof(buf), "%.17e", n->val.dval);
+ break;
+ }
+ break;
+ case PTBOOL:
+ switch(n->val.ctype) {
+ default:
+ goto badlit;
+ case CTBOOL:
+ snprint(buf, sizeof(buf), "%lld", n->val.vval);
+ break;
+ }
+ break;
+ case PTPTR:
+ switch(n->val.ctype) {
+ default:
+ goto badlit;
+ case CTSTR:
+ snprint(buf, sizeof(buf), "\"%Z\"", n->val.sval);
+ break;
+ case CTNIL:
+ snprint(buf, sizeof(buf), "(void*)0", n->val.sval);
+ break;
+ }
+ break;
+
+ case PTSTRING:
+ snprint(buf, sizeof(buf), "(_T_Z)&slit");
+ break;
+
+ }
+ break;
+ }
+
+out:
+ return fmtstrcpy(fp, buf);
+}
+
+char*
+thistypenam(Node *t)
+{
+ char *typ;
+ Node *n;
+
+ typ = "???";
+ if(t == N)
+ return typ;
+ n = getthisx(t); // struct{field a *T}
+ if(n != N)
+ n = n->type; // field a *T
+ if(n != N)
+ n = n->type; // *T
+ if(n != N)
+ n = n->type; // T
+ if(n != N && n->sym != S)
+ typ = n->sym->name;
+ return typ;
+}
+
+void
+dumpfunct(Plist *pl)
+{
+ Node *t;
+ char *pkg, *typ, *fun;
+
+ t = pl->name->type;
+ pkg = pl->name->sym->opackage;
+ fun = pl->name->sym->name;
+
+ if(t->thistuple > 0) {
+ typ = thistypenam(t); // struct{field a *T}
+ Bprint(bout, "\n%C %s_%s_%s%lC", t, pkg, typ, fun, t);
+ } else {
+ Bprint(bout, "\n%C %s_%s%lC", t, pkg, fun, t);
+ }
+
+ Bprint(bout, "\n{\n");
+ doframe(pl->locals, "local");
+}
+
+void
+dumpmethods()
+{
+ Node *t;
+ char *pkg, *typ, *fun;
+ Plist *pl;
+
+ for(pl=plist; pl!=nil; pl=pl->link) {
+ t = pl->name->type;
+ if(t->thistuple > 0) {
+ pkg = pl->name->sym->opackage;
+ fun = pl->name->sym->name;
+ typ = thistypenam(t);
+ Bprint(bout, "\n%C %s_%s_%s%lC;\n", t, pkg, typ, fun, t);
+ }
+ }
+}
+
+static int
+sigcmp(Sig *a, Sig *b)
+{
+ return strcmp(a->fun, b->fun);
+}
+
+void
+dumpsignatures(void)
+{
+ Dcl *d;
+ Node *t, *f;
+ Sym *s1, *s;
+ char *pkg, *typ, *fun;
+ int et, o, any;
+ Sig *a, *b;
+
+ /* put all the names into a linked
+ * list so that it may be generated in sorted order.
+ * the runtime will be linear rather than quadradic
+ */
+
+ any = 1;
+ for(d=externdcl; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+
+ t = d->dnode;
+ et = t->etype;
+ if(et != TSTRUCT && et != TINTER)
+ continue;
+
+ s = d->dsym;
+ if(s == S)
+ continue;
+
+ typ = s->name;
+ if(typ[0] == '_')
+ continue;
+
+ pkg = s->opackage;
+ if(pkg != package) {
+ if(et == TINTER)
+ Bprint(bout, "extern _Sigi sig_%s_%s[];\n", pkg, typ);
+ else
+ Bprint(bout, "extern _Sigs sig_%s_%s[];\n", pkg, typ);
+ continue;
+ }
+
+ a = nil;
+ o = 0;
+ for(f=t->type; f!=N; f=f->down) {
+ if(f->type->etype != TFUNC)
+ continue;
+
+ if(f->etype != TFIELD)
+ fatal("dumpsignatures: not field");
+
+ s1 = f->sym;
+ if(s1 == nil)
+ continue;
+ fun = s1->name;
+ if(fun[0] == '_')
+ continue;
+
+ b = mal(sizeof(*b));
+ b->link = a;
+ a = b;
+
+ a->fun = fun;
+ a->hash = PRIME8*stringhash(fun) + PRIME9*typehash(f->type, 0);
+ a->offset = o;
+ o++;
+ }
+
+ if(1 || et == TINTER || a != nil) {
+ if(any) {
+ Bprint(bout, "\n");
+ any = 0;
+ }
+
+ a = lsort(a, sigcmp);
+
+ if(et == TINTER) {
+ o = 0;
+ for(b=a; b!=nil; b=b->link)
+ o++;
+ Bprint(bout, "_Sigi sig_%s_%s[] =\n", pkg, typ);
+ Bprint(bout, "{\n");
+ Bprint(bout, "\t{ \"\", 0, %d}, // count\n", o);
+ for(b=a; b!=nil; b=b->link) {
+ Bprint(bout, "\t{ \"%s\", 0x%.8lux, %d},\n",
+ b->fun, b->hash, b->offset);
+ }
+ } else {
+ Bprint(bout, "_Sigs sig_%s_%s[] =\n", pkg, typ);
+ Bprint(bout, "{\n");
+ for(b=a; b!=nil; b=b->link) {
+ Bprint(bout, "\t{ \"%s\", 0x%.8lux, &%s_%s_%s },\n",
+ b->fun, b->hash, pkg, typ, b->fun);
+ }
+ }
+ Bprint(bout, "\t{ 0,0,0 }\n");
+ Bprint(bout, "};\n");
+ }
+ }
+}
+
+int
+istypstr(Node *t)
+{
+ if(t == N)
+ fatal("istypstr: t nil");
+ if(t->etype == TSTRUCT)
+ return 1;
+ return 0;
+}
+
+static int XXX = 0;
+static int YYY = 0;
+
+int
+alldefined(Node *t, int first)
+{
+ Node *t1;
+
+ if(t == N)
+ return 1;
+
+ if(t->op != OTYPE)
+ fatal("alldefined: not OTYPE: %O", t->op);
+
+ if(t->recur)
+ return 1;
+
+ if(!first && t->sym!=S && t->sym->undef != 0)
+ return 1;
+
+ t->recur++;
+
+ switch(t->etype) {
+ default:
+ // should be basic types
+ return 1;
+
+ case TPTR:
+ case TARRAY:
+ case TFIELD:
+ if(!alldefined(t->type, 0))
+ goto no;
+ break;
+
+ case TSTRUCT:
+ case TFUNC:
+ for(t1=t->type; t1!=N; t1=t1->down) {
+ if(!alldefined(t1, 0))
+ goto no;
+ }
+ break;
+ }
+
+ t->recur--;
+ return 1;
+
+no:
+ t->recur--;
+ return 0;
+}
+
+void
+doframe(Dcl *r, char *msg)
+{
+ Sym *s;
+ Dcl *d;
+ Node *n, *t;
+ int flag, pass, any;
+ char *tab, *nam, *pkg, *typ;
+
+ tab = "\t";
+ if(msg[0] != 'l')
+ tab = "";
+
+ // put out types
+ flag = 1;
+ typeexpand = 1;
+ for(pass=0;; pass++) {
+if(XXX)print("\npass %d\n\n", pass);
+ any = 0;
+ for(d=r; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+
+ if(flag) {
+ Bprint(bout, "\n%s// %s types\n", tab, msg);
+ flag = 0;
+ }
+
+ n = d->dnode;
+ nam = "???";
+ s = d->dsym;
+ if(s != S)
+ nam = s->name;
+
+ if(pass == 0) {
+ if(s != S)
+ s->undef = 0;
+ if(istypstr(n)) {
+ Bprint(bout, "%stypedef struct _T_%ld _T_%ld; // %s\n",
+ tab, n->vargen, n->vargen, nam);
+if(XXX)print("\t1 pass-%d ", pass);
+if(XXX)print("typedef struct _T_%ld _T_%ld; // %s\n", n->vargen, n->vargen, nam);
+ }
+ any = 1;
+ continue;
+ }
+
+if(XXX)if(s != S) print("looking at %s undef=%d: %lT\n", s->name, s->undef, n);
+
+ if(s != S && s->undef == 0 && alldefined(n, 1)) {
+if(XXX)print("\t2 pass-%d ", pass);
+ if(istypstr(n)) {
+ Bprint(bout, "%sstruct _T_%ld %hC; // %s\n",
+ tab, n->vargen, n, nam);
+if(XXX)print("struct _T_%ld %hC; // %s\n", n->vargen, n, nam);
+ } else {
+ if(n->etype != TFUNC)
+ Bprint(bout, "%stypedef %C _T_%ld%lC; // %s\n",
+ tab, n, n->vargen, n, nam);
+if(XXX)print("typedef %C _T_%ld%lC; // %s\n", n, n->vargen, n, nam);
+ }
+ s->undef = 1;
+ any = 1;
+ }
+ }
+ if(any)
+ continue;
+
+ for(d=r; d!=D; d=d->forw) {
+ if(d->op != OTYPE)
+ continue;
+ n = d->dnode;
+ s = d->dsym;
+ if(s != S) {
+ if(s->undef == 0)
+ fatal("doframe: couldnt resolve type %s %lT\n",
+ s->name, n);
+ continue;
+ }
+if(XXX)print("\t-3 pass-%d ", pass);
+ if(istypstr(n)) {
+ Bprint(bout, "%sstruct _T_%ld %hC;\n",
+ tab, n->vargen, n);
+if(XXX)print("struct _T_%ld %hC;\n", n->vargen, n);
+ } else {
+ Bprint(bout, "%stypedef %C _T_%ld%lC;\n",
+ tab, n, n->vargen, n);
+if(XXX)print("typedef %C _T_%ld%lC;\n", n, n->vargen, n);
+ }
+ }
+ break;
+ }
+ typeexpand = 0;
+
+ flag = 1;
+ for(d=r; d!=D; d=d->forw) {
+ if(d->op != ONAME)
+ continue;
+
+ if(flag) {
+ Bprint(bout, "\n%s// %s variables\n", tab, msg);
+ flag = 0;
+ }
+
+ nam = "???";
+ pkg = nam;
+ s = d->dsym;
+ if(s != S) {
+ nam = s->name;
+ pkg = s->opackage;
+ }
+
+ n = d->dnode;
+ t = n->type;
+ if(n->vargen != 0) {
+if(YYY) print("nam-1 %s\n", nam);
+ Bprint(bout, "%s%C _V_%ld%lC; // %s\n",
+ tab, t, n->vargen, t, nam);
+ continue;
+ }
+
+ if(t->etype == TFUNC && t->thistuple > 0) {
+if(YYY) print("nam-2 %s\n", nam);
+ typ = thistypenam(t);
+ Bprint(bout, "%s%C %s_%s_%s%lC;\n",
+ tab, t, pkg, typ, nam, t);
+ continue;
+ }
+
+if(YYY) print("nam-3 %E %s %lT\n", t->etype, nam, t);
+ Bprint(bout, "%s%C %s_%s%lC;\n",
+ tab, t, pkg, nam, t);
+ }
+}
+
+/*
+ * open the frame
+ * declare dummy this/in/out args
+ */
+void
+docall1(Prog *p)
+{
+ Node *f, *t, *n;
+
+ if(p->addr.type != ANODE)
+ goto bad;
+
+ f = p->addr.node;
+ if(f == N)
+ goto bad;
+ t = f->type;
+ if(t == N)
+ goto bad;
+ if(t->etype == TPTR)
+ t = t->type;
+ if(t->etype != TFUNC)
+ goto bad;
+
+ Bprint(bout, "\t{\n"); // open a block - closed in CALL2/CALL3
+
+ if(t->thistuple > 0) {
+ n = *getthis(t);
+ if(n->nname == N)
+ goto bad;
+ Bprint(bout, "\t\t_T_%ld _V_%ld; // %S\n", n->vargen, n->nname->vargen, n->sym);
+ }
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ if(n->nname == N)
+ goto bad;
+ Bprint(bout, "\t\t_T_%ld _V_%ld; // %S\n", n->vargen, n->nname->vargen, n->sym);
+ }
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ if(n->nname == N)
+ goto bad;
+ Bprint(bout, "\t\t_T_%ld _V_%ld; // %S\n", n->vargen, n->nname->vargen, n->sym);
+ }
+
+ return;
+
+bad:
+ fatal("docall1: bad %P", p);
+}
+
+/*
+ * call the function
+ */
+void
+docall2(Prog *p)
+{
+ Node *f, *t, *n;
+
+ if(p->addr.type != ANODE)
+ goto bad;
+ f = p->addr.node;
+ if(f == N)
+ goto bad;
+ t = f->type;
+ if(t == N || t->etype != TFUNC)
+ goto bad;
+
+ Bprint(bout, "\t%D(", p);
+
+ if(t->thistuple > 0) {
+ n = *getthis(t);
+ Bprint(bout, "&_V_%ld", n->nname->vargen);
+ } else
+ Bprint(bout, "0");
+
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ Bprint(bout, ", &_V_%ld", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0");
+
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ Bprint(bout, ", &_V_%ld);\n", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0);\n");
+
+ return;
+
+bad:
+ fatal("docall2: bad");
+}
+
+/*
+ * call the function indirect
+ */
+void
+docalli2(Prog *p)
+{
+ Node *f, *t, *n;
+
+ if(p->addr.type != ANODE)
+ goto bad;
+ f = p->addr.node;
+ if(f == N)
+ goto bad;
+ t = f->type;
+ if(t == N || t->etype != TPTR)
+ goto bad;
+ t = t->type;
+ if(t->etype != TFUNC)
+ goto bad;
+
+ // pass one -- declare the prototype
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ Bprint(bout, "\t(*(void(*)(void*, _T_%ld*", n->vargen);
+ } else
+ Bprint(bout, "\t(*(void(*)(void*, void*");
+
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ Bprint(bout, ", _T_%ld*)", n->vargen);
+ } else
+ Bprint(bout, ", void*)");
+
+ // pass two -- pass the arguments
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ Bprint(bout, ")%R)(0, &_V_%ld", PTPTR, n->nname->vargen);
+ } else
+ Bprint(bout, ")%R)(0, 0", PTPTR);
+
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ Bprint(bout, ", &_V_%ld);\n", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0);\n");
+
+ return;
+
+bad:
+ fatal("docalli2: bad");
+}
+
+/*
+ * call the method
+ */
+void
+docallm2(Prog *p)
+{
+ Node *f, *t, *n;
+ char *pkg, *typ, *nam;
+
+ if(p->addr.type != ANODE)
+ goto bad;
+ f = p->addr.node;
+ if(f == N || f->op != ODOTMETH)
+ goto bad;
+ t = f->type;
+ if(t == N || t->etype != TFUNC)
+ goto bad;
+
+ nam = "???";
+ pkg = nam;
+ typ = nam;
+
+ // get the structure name
+ n = f->left;
+ if(n != N)
+ n = n->type;
+ if(n->op == OTYPE && n->etype == TPTR)
+ n = n->type;
+ if(n->sym != S) {
+ typ = n->sym->name;
+ pkg = n->sym->opackage;
+ }
+
+ // get the function name
+ n = f->right;
+ if(n != N && n->op == ONAME && n->sym != S)
+ nam = n->sym->name;
+
+ Bprint(bout, "\t%s_%s_%s(%R", pkg, typ, nam, PTPTR);
+
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ Bprint(bout, ", (void*)&_V_%ld", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0");
+
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ Bprint(bout, ", (void*)&_V_%ld);\n", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0);\n");
+
+ return;
+
+bad:
+ fatal("docallm2: bad");
+}
+
+/*
+ * call the interface method
+ */
+void
+docallf2(Prog *p)
+{
+ Node *f, *t, *n;
+ int offset;
+
+ if(p->addr.type != ANODE)
+ goto bad;
+ f = p->addr.node;
+ if(f == N || f->op != ODOTINTER)
+ goto bad;
+ t = f->type;
+ if(t == N || t->etype != TFUNC)
+ goto bad;
+
+ offset = 0;
+
+ Bprint(bout, "\t(_U._R_I.m->fun[%d])(_U._R_I.s", f->kaka);
+
+ if(t->outtuple > 0) {
+ n = *getoutarg(t);
+ Bprint(bout, ", (void*)&_V_%ld", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0");
+
+ if(t->intuple > 0) {
+ n = *getinarg(t);
+ Bprint(bout, ", (void*)&_V_%ld);\n", n->nname->vargen);
+ } else
+ Bprint(bout, ", 0);\n");
+
+ return;
+
+bad:
+ fatal("docallf2: bad");
+}
+
+/*
+ * close the frame
+ */
+void
+docall3(Prog *p)
+{
+ Bprint(bout, "\t}\n");
+}
+
+char*
+signame(Node *t)
+{
+// this code sb merged with thistypename
+ static char name[100];
+ char *typ, *pkg;
+
+ typ = "???";
+ pkg = typ;
+
+ if(t == N || t->op != OTYPE)
+ goto out;
+
+ if(t->etype == TPTR) {
+ t = t->type;
+ if(t == N)
+ goto out;
+ }
+ if(t->sym == S)
+ goto out;
+ typ = t->sym->name;
+ pkg = t->sym->opackage; // this may not be correct
+
+out:
+ snprint(name, sizeof(name), "sig_%s_%s", pkg, typ);
+ return name;
+}
+
+void
+doconv(Prog *p)
+{
+ Node *n, *tl, *tr;
+ int l, pt;
+
+ if(p->pt != PTNIL) {
+ Bprint(bout, "\t%R = %R;\n", p->pt, p->pt1);
+ return;
+ }
+
+ n = p->addr.node;
+ if(p->addr.type != ANODE || n == N || n->op != OCONV)
+ fatal("doconv: PCONV-N not OCONV");
+
+ tl = n->left;
+ tr = n->right;
+
+ if(isinter(tl)) {
+ if(isptrto(tr, TSTRUCT)) {
+ Bprint(bout, "\tconvertStoI(%s, ", signame(tl));
+ Bprint(bout, "%s); // _U._R_I = _U._R_P\n",
+ signame(tr));
+ return;
+ }
+ if(isinter(tr)) {
+ Bprint(bout, "\tconvertItoI(%s); // _U._R_I = _U._R_I\n",
+ signame(tl));
+ return;
+ }
+ }
+ if(isptrto(tl, TSTRUCT) && isinter(tr)) {
+ Bprint(bout, "\t%R = %R.s;\n", TPTR, PTINTER);
+ return;
+ }
+ if(isint[tl->etype] || isfloat[tl->etype]) {
+ if(isint[tr->etype] || isfloat[tr->etype]) {
+ Bprint(bout, "\t%R = %R;\n", conv2pt(tl), conv2pt(tr));
+ return;
+ }
+ }
+
+ if(isptrto(tl, TSTRING)) {
+ if(isint[tr->etype]) {
+ Bprint(bout, "\tconvertItoZ(%R);\n", conv2pt(tr));
+ return;
+ }
+ l = isbytearray(tr);
+ if(l > 0) {
+ pt = PTADDR;
+ if(tr->etype == TPTR)
+ pt = TPTR;
+ Bprint(bout, "\tconvertBtoZ(%R, %d);\n", pt, l-1);
+ return;
+ }
+ }
+
+ fatal("doconv: %T = %T", tl, tr);
+}
+
+char*
+getfmt(int pt)
+{
+ switch(pt) {
+ default:
+ return "D";
+
+ case PTUINT8:
+ case PTUINT16:
+ case PTUINT32:
+ case PTUINT64:
+ return "UD";
+
+ case PTFLOAT32:
+ case PTFLOAT64:
+ case PTFLOAT80:
+ return "F";
+
+ case PTSTRING:
+ return "Z";
+ }
+}