diff options
author | Rob Pike <r@golang.org> | 2008-06-04 14:46:07 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2008-06-04 14:46:07 -0700 |
commit | 5cf1e37b96825023b2da8de9be3a07d1987bb306 (patch) | |
tree | fda9e615c7d6ddb748cee567027fae05ba9215ae /src/old/c/obj.c | |
parent | 0a2697043d69739b27b6ba872b2092a4c2bb61a8 (diff) | |
download | golang-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.c | 1556 |
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"; + } +} |