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/gen.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/gen.c')
-rw-r--r-- | src/old/c/gen.c | 1186 |
1 files changed, 1186 insertions, 0 deletions
diff --git a/src/old/c/gen.c b/src/old/c/gen.c new file mode 100644 index 000000000..dc9e55038 --- /dev/null +++ b/src/old/c/gen.c @@ -0,0 +1,1186 @@ +// 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" + +#undef EXTERN +#define EXTERN +#include "gen.h" + +static Node* curfn; + +void +compile(Node *fn) +{ + Plist *pl; + + if(fn->nbody == N) + return; + if(nerrors != 0) { + walk(fn); + return; + } + + if(debug['w']) + dump("--- pre walk ---", fn->nbody); + walk(fn); + if(nerrors != 0) + return; + if(debug['w']) + dump("--- post walk ---", fn->nbody); + + curfn = fn; + + continpc = P; + breakpc = P; + + pc = mal(sizeof(*pc)); + firstpc = pc; + pc->op = PEND; + pc->addr.type = ANONE; + pc->loc = 1; + inarggen(); + gen(curfn->nbody); + + if(curfn->type->outtuple != 0) + gopcodet(PPANIC, N, N); + + if(debug['p']) + proglist(); + + pl = mal(sizeof(*pl)); + pl->name = curfn->nname; + pl->locals = autodcl; + pl->firstpc = firstpc; + + if(plist == nil) + plist = pl; + else + plast->link = pl; + plast = pl; + + if(debug['f']) + frame(0); +} + +/* + * compile statements + */ +void +gen(Node *n) +{ + long lno; + Prog *scontin, *sbreak; + Prog *p1, *p2, *p3; + Sym *s; + + lno = dynlineno; + +loop: + if(n == N) + goto ret; + dynlineno = n->lineno; // for diagnostics + + switch(n->op) { + default: + dump("gen: unknown op", n); + break; + + case OLIST: + gen(n->left); + n = n->right; + goto loop; + + case OPANIC: + case OPRINT: + genprint(n->left); + if(n->op == OPANIC) + gopcodet(PPANIC, N, N); + break; + + case OCASE: + case OFALL: + case OXCASE: + case OXFALL: + case OEMPTY: + break; + + case OLABEL: + // before declaration, s->label points at + // a link list of PXGOTO instructions. + // after declaration, s->label points + // at a PGOTO to .+1 + + s = n->left->sym; + p1 = (Prog*)s->label; + + if(p1 != P) { + if(p1->op == PGOTO) { + yyerror("label redeclared: %S", s); + break; + } + while(p1 != P) { + if(p1->op != PGOTOX) + fatal("bad label pointer: %S", s); + p2 = p1->addr.branch; + p1->addr.branch = pc; + p1->op = PGOTO; + p1 = p2; + } + } + + s->label = pc; + p1 = gbranch(PGOTO, N); + patch(p1, pc); + break; + + case OGOTO: + s = n->left->sym; + p1 = (Prog*)s->label; + if(p1 != P && p1->op == PGOTO) { + // already declared + p2 = gbranch(PGOTO, N); + patch(p2, p1->addr.branch); + break; + } + + // not declaraed yet + p2 = gbranch(PGOTOX, N); + p2->addr.node = n; // info for diagnostic if never declared + patch(p2, p1); + s->label = p2; + break; + + case OBREAK: + if(breakpc == P) { + yyerror("gen: break is not in a loop"); + break; + } + patch(gbranch(PGOTO, N), breakpc); + break; + + case OCONTINUE: + if(continpc == P) { + yyerror("gen: continue is not in a loop"); + break; + } + patch(gbranch(PGOTO, N), continpc); + break; + + case OFOR: + gen(n->ninit); // init + p1 = gbranch(PGOTO, N); // goto test + sbreak = breakpc; + breakpc = gbranch(PGOTO, N); // break: goto done + scontin = continpc; + continpc = pc; + gen(n->nincr); // contin: incr + patch(p1, pc); // test: + bgen(n->ntest, 0, breakpc); // if(!test) goto break + gen(n->nbody); // body + patch(gbranch(PGOTO, N), continpc); // goto contin + patch(breakpc, pc); // done: + continpc = scontin; + breakpc = sbreak; + break; + + case OIF: + gen(n->ninit); // init + p1 = gbranch(PGOTO, N); // goto test + p2 = gbranch(PGOTO, N); // p2: goto else + patch(p1, pc); // test: + bgen(n->ntest, 0, p2); // if(!test) goto p2 + gen(n->nbody); // then + p3 = gbranch(PGOTO, N); // goto done + patch(p2, pc); // else: + gen(n->nelse); // else + patch(p3, pc); // done: + break; + + case OSWITCH: + gen(n->ninit); // init + p1 = gbranch(PGOTO, N); // goto test + sbreak = breakpc; + breakpc = gbranch(PGOTO, N); // break: goto done + patch(p1, pc); // test: + swgen(n); // switch(test) body + patch(breakpc, pc); // done: + breakpc = sbreak; + break; + + case OASOP: + cgen_asop(n->left, n->right, n->kaka); + break; + + case OAS: + cgen_as(n->left, n->right, n->op, n->kaka); + break; + + case OCALL: + case OCALLPTR: + case OCALLMETH: + case OCALLINTER: + cgen_call(n, 1); + break; + + case ORETURN: + cgen_ret(n); + break; + } + +ret: + dynlineno = lno; +} + +/* + * compile expression to (unnamed) reg + */ +void +cgen(Node *n) +{ + long lno; + Node *nl, *nr, *r; + int a; + Prog *p1, *p2, *p3; + + if(n == N) + return; + + lno = dynlineno; + if(n->op != ONAME) + dynlineno = n->lineno; // for diagnostics + + nl = n->left; + nr = n->right; + + if(nr != N && nr->ullman >= UINF && nl != N && nl->ullman >= UINF) { + cgen(nr); + r = tempname(n->type); + gopcodet(PSTORE, n->type, r); + nr = r; + } + + switch(n->op) { + default: + yyerror("cgen: unknown op %O", n->op); + break; + + case ONAME: + case OLITERAL: + gopcodet(PLOAD, n->type, n); + break; + + case ONEW: + gopcodet(PNEW, n->type, n); + break; + + // these call bgen to get a bool value + case OOROR: + case OANDAND: + case OEQ: + case ONE: + case OLT: + case OLE: + case OGE: + case OGT: + case ONOT: + p1 = gbranch(PGOTO, N); + p2 = gopcodet(PLOAD, n->type, booltrue); + p3 = gbranch(PGOTO, N); + patch(p1, pc); + bgen(n, 1, p2); + p2 = gopcodet(PLOAD, n->type, boolfalse); + patch(p3, pc); + goto ret; + + case OPLUS: + cgen(nl); + goto ret; + + // unary + case OMINUS: + case OCOM: + a = optopop(n->op); + goto uop; + + // symmetric binary + case OAND: + case OOR: + case OXOR: + case OADD: + case OMUL: + a = optopop(n->op); + goto sbop; + + // asymmetric binary + case OMOD: + case OSUB: + case ODIV: + case OLSH: + case ORSH: + case OCAT: + a = optopop(n->op); + goto abop; + + case OCONV: + if(isbytearray(nl->type)) { + if(nl->type->etype == TPTR) + cgen(nl); + else + agen(nl); + gopcode(PCONV, PTNIL, nod(OCONV, n->type, nl->type)); + break; + } + + cgen(nl); + gopcode(PCONV, PTNIL, nod(OCONV, n->type, nl->type)); + break; + + case OINDEXPTRSTR: + nl = n->left; + nr = n->right; + if(nl->addable) { + cgen(nr); + cgen(nl); + gopcode(PLOADI, PTADDR, N); + gopcodet(PINDEXZ, nr->type, N); + break; + } +fatal("xxx"); + break; + + case OINDEXSTR: + nl = n->left; + nr = n->right; + if(nl->addable) { + cgen(nr); + gopcodet(PINDEXZ, nr->type, nl); + break; + } + cgen(nl); + r = tempname(nl->type); + gopcodet(PSTORE, nl->type, r); + cgen(nr); + gopcodet(PINDEXZ, nr->type, r); + break; + + case OSLICESTR: + case OSLICEPTRSTR: + nl = n->left; // name + nr = n->right; + + r = nr->right; // index2 + if(!r->addable) { + cgen(r); + r = tempname(r->type); + gopcodet(PSTORE, r->type, r); + } + + // string into PTADDR + if(!nl->addable) { + cgen(nl); + gconv(PTADDR, nl->type->etype); + } else + gopcode(PLOAD, PTADDR, nl); + + if(n->op == OSLICEPTRSTR) + gopcode(PLOADI, PTADDR, N); + + // offset in int reg + cgen(nr->left); + + // index 2 addressed + gopcodet(PSLICE, r->type, r); + break; + + case OINDEXPTR: + case OINDEX: + case ODOT: + case ODOTPTR: + case OIND: + agen(n); + gopcodet(PLOADI, n->type, N); + break; + + case OLEN: + cgen(nl); + gopcodet(PLEN, nl->type, nl); + break; + + case ODOTMETH: + case ODOTINTER: + cgen(n->left); + break; + + case OADDR: + agen(nl); + gconv(PTPTR, PTADDR); + break; + + case OCALL: + case OCALLPTR: + case OCALLMETH: + case OCALLINTER: + cgen_call(n, 0); + cgen_callret(n, N); + break; + } + goto ret; + +sbop: // symmetric + if(nl->ullman < nr->ullman) { + r = nl; + nl = nr; + nr = r; + } + +abop: // asymmetric + if(nr->addable) { + cgen(nl); + gopcodet(a, n->type, nr); + goto ret; + } + + cgen(nr); + r = tempname(n->type); + gopcodet(PSTORE, n->type, r); + cgen(nl); + gopcodet(a, n->type, r); + goto ret; + +uop: // unary + cgen(nl); + gopcodet(a, n->type, N); + goto ret; + +ret: + dynlineno = lno; +} + +/* + * compile the address of a value + */ +void +agen(Node *n) +{ + Node *nl, *nr; + Node *t, *r; + + if(n == N || n->type == N) + return; + switch(n->op) { + default: + dump("agen: unknown op", n); + break; + + case ONAME: + gopcode(PADDR, PTADDR, n); + break; + + case OINDEXPTR: + nl = n->left; + nr = n->right; + if(nl->addable) { + cgen(nr); + gopcode(PLOAD, PTADDR, nl); + genindex(n); + break; + } + if(nr->addable) { + cgen(nl); + gconv(PTADDR, nl->type->etype); + cgen(nr); + genindex(n); + break; + } + cgen(nr); + r = tempname(n->type); + gopcodet(PSTORE, n->type, r); + cgen(nl); + gconv(PTADDR, nl->type->etype); + cgen(r); + genindex(n); + break; + + case OINDEX: + nl = n->left; + nr = n->right; + if(nl->addable) { + cgen(nr); + agen(nl); + genindex(n); + break; + } + if(nr->addable) { + agen(nl); + cgen(nr); + genindex(n); + break; + } + cgen(nr); + r = tempname(n->type); + gopcodet(PSTORE, n->type, r); + agen(nl); + cgen(r); + genindex(n); + break; + + case OIND: + nl = n->left; + if(nl->addable) { + gopcode(PLOAD, PTADDR, nl); + break; + } + cgen(nl); + gconv(PTADDR, nl->type->etype); + break; + + case ODOT: + case ODOTPTR: + nl = n->left; + nr = n->right; + t = nl->type; + switch(t->etype) { + default: + badtype(n->op, n->left->type, n->right->type); + break; + + case TPTR: + if(nl->op != ONAME) { + cgen(nl); + gconv(PTADDR, nl->type->etype); + } else + gopcode(PLOAD, PTADDR, nl); + gaddoffset(nr); + break; + + case TSTRUCT: + agen(nl); + gaddoffset(nr); + break; + } + break; + } +} + +/* + * compile boolean expression + * true is branch-true or branch-false + * to is where to branch + */ +void +bgen(Node *n, int true, Prog *to) +{ + long lno; + int et, a; + Node *nl, *nr, *r; + Prog *p1, *p2; + + if(n == N) + n = booltrue; + + lno = dynlineno; + if(n->op != ONAME) + dynlineno = n->lineno; // for diagnostics + + if(n == N) + goto ret; + if(n->type == N) { + convlit(n, types[TBOOL]); + if(n->type == N) + goto ret; + } + + et = n->type->etype; + if(et != TBOOL) { + yyerror("cgen: bad type %T for %O", n->type, n->op); + patch(gbranch(PERROR, N), to); + goto ret; + } + nl = N; + nr = N; + + switch(n->op) { + default: + cgen(n); + gopcodet(PTEST, n->type, N); + a = PBTRUE; + if(!true) + a = PBFALSE; + patch(gbranch(a, n->type), to); + goto ret; + + case OLITERAL: + if(!true == !n->val.vval) + patch(gbranch(PGOTO, N), to); + goto ret; + + case ONAME: + gopcodet(PTEST, n->type, n); + a = PBTRUE; + if(!true) + a = PBFALSE; + patch(gbranch(a, n->type), to); + goto ret; + + case OANDAND: + if(!true) + goto caseor; + + caseand: + p1 = gbranch(PGOTO, N); + p2 = gbranch(PGOTO, N); + patch(p1, pc); + bgen(n->left, !true, p2); + bgen(n->right, !true, p2); + p1 = gbranch(PGOTO, N); + patch(p1, to); + patch(p2, pc); + goto ret; + + case OOROR: + if(!true) + goto caseand; + + caseor: + bgen(n->left, true, to); + bgen(n->right, true, to); + goto ret; + + case OEQ: + case ONE: + case OLT: + case OGT: + case OLE: + case OGE: + nr = n->right; + if(nr == N || nr->type == N) + goto ret; + + case ONOT: // unary + nl = n->left; + if(nl == N || nl->type == N) + goto ret; + } + + switch(n->op) { + + case ONOT: + bgen(nl, !true, to); + goto ret; + + case OEQ: a = PBEQ; goto br; + case ONE: a = PBNE; goto br; + case OLT: a = PBLT; goto br; + case OGT: a = PBGT; goto br; + case OLE: a = PBLE; goto br; + case OGE: a = PBGE; goto br; + br: + if(!true) + a = brcom(a); + + // make simplest on right + if(nl->ullman < nr->ullman) { + a = brrev(a); + r = nl; + nl = nr; + nr = r; + } + + if(nr->addable) { + cgen(nl); + gopcodet(PCMP, nr->type, nr); + patch(gbranch(a, nr->type), to); + break; + } + cgen(nr); + r = tempname(nr->type); + gopcodet(PSTORE, nr->type, r); + cgen(nl); + gopcodet(PCMP, nr->type, r); + patch(gbranch(a, nr->type), to); + break; + } + goto ret; + +ret: + dynlineno = lno; +} + +void +swgen(Node *n) +{ + Node *c1, *c2; + Case *s0, *se, *s; + Prog *p1, *dflt; + long lno; + int any; + Iter save1, save2; + + lno = dynlineno; + + p1 = gbranch(PGOTO, N); + s0 = C; + se = C; + + // walk thru the body placing breaks + // and labels into the case statements + + any = 0; + dflt = P; + c1 = listfirst(&save1, &n->nbody); + while(c1 != N) { + dynlineno = c1->lineno; // for diagnostics + if(c1->op != OCASE) { + if(s0 == C) + yyerror("unreachable statements in a switch"); + gen(c1); + + any = 1; + if(c1->op == OFALL) + any = 0; + c1 = listnext(&save1); + continue; + } + + // put in the break between cases + if(any) { + patch(gbranch(PGOTO, N), breakpc); + any = 0; + } + + // over case expressions + c2 = listfirst(&save2, &c1->left); + if(c2 == N) + dflt = pc; + + while(c2 != N) { + + s = mal(sizeof(*s)); + if(s0 == C) + s0 = s; + else + se->slink = s; + se = s; + + s->scase = c2; // case expression + s->sprog = pc; // where to go + + c2 = listnext(&save2); + } + + c1 = listnext(&save1); + } + + if(any) + patch(gbranch(PGOTO, N), breakpc); + + patch(p1, pc); + c1 = tempname(n->ntest->type); + cgen(n->ntest); + gopcodet(PSTORE, n->ntest->type, c1); + + for(s=s0; s!=C; s=s->slink) { + cgen(s->scase); + gopcodet(PCMP, n->ntest->type, c1); + patch(gbranch(PBEQ, n->ntest->type), s->sprog); + } + if(dflt != P) { + patch(gbranch(PGOTO, N), dflt); + goto ret; + } + patch(gbranch(PGOTO, N), breakpc); + +ret: + dynlineno = lno; +} + +/* + * does this tree use + * the pointer register + */ +int +usesptr(Node *n) +{ +// if(n->addable) +// return 0; + return 1; +} + +void +cgen_as(Node *nl, Node *nr, int op, int kaka) +{ + Node *r; + +loop: + switch(op) { + default: + fatal("cgen_as: unknown op %O", op); + + case OAS: + if(nr == N && nl->op == OLIST) { + kaka = PAS_SINGLE; + cgen_as(nl->left, nr, op, kaka); + nl = nl->right; + goto loop; + } + switch(kaka) { + default: + yyerror("cgen_as: unknown param %d %d", kaka, PAS_CALLM); + break; + + case PAS_CALLM: // function returning multi values + cgen_call(nr, 0); + cgen_callret(nr, nl); + break; + + case PAS_SINGLE: // single return val used in expr + if(nr == N || isnil(nr)) { + if(nl->addable) { + gopcodet(PSTOREZ, nl->type, nl); + break; + } + agen(nl); + gopcodet(PSTOREZI, nl->type, N); + break; + } + + if(nl->addable) { + cgen(nr); + genconv(nl, nr); + gopcodet(PSTORE, nl->type, nl); + break; + } + + if(nr->addable && !needconvert(nl->type, nr->type)) { + agen(nl); + gopcodet(PSTOREI, nr->type, nr); + break; + } + if(!usesptr(nr)) { + cgen(nr); + genconv(nl, nr); + agen(nl); + gopcodet(PSTOREI, nr->type, N); + break; + } + agen(nl); + r = tempname(ptrto(nl->type)); + gopcode(PSTORE, PTADDR, r); + cgen(nr); + genconv(nl, nr); + gopcode(PLOAD, PTADDR, r); + gopcodet(PSTOREI, nl->type, N); + break; + + case PAS_STRUCT: // structure assignment + r = ptrto(nr->type); + if(!usesptr(nr)) { + agen(nr); + agen(nl); + gopcodet(PLOAD, N, r); + gopcodet(PERROR, nr->type, N); + break; + } + r = tempname(r); + agen(nr); + gopcode(PSTORE, PTADDR, r); + + agen(nl); + gopcodet(PERROR, nr->type, r); + break; + } + break; + } +} + +void +cgen_asop(Node *nl, Node *nr, int op) +{ + Node *r; + int a; + + a = optopop(op); + if(nr->addable) { + if(nl->addable) { + gopcodet(PLOAD, nl->type, nl); + gopcodet(a, nr->type, nr); + gopcodet(PSTORE, nl->type, nl); + return; + } + + agen(nl); + gopcodet(PLOADI, nl->type, N); + gopcodet(a, nr->type, nr); + gopcodet(PSTOREI, nl->type, N); + return; + } + + r = tempname(nr->type); + cgen(nr); + gopcodet(PSTORE, nr->type, r); + + agen(nl); + gopcodet(PLOADI, nl->type, N); + gopcodet(a, nr->type, r); + gopcodet(PSTOREI, nl->type, N); +} + +void +inarggen(void) +{ + Iter save; + Node *arg, *t; + int i; + + t = curfn->type; + + arg = structfirst(&save, getthis(t)); + if(arg != N) { + fnparam(t, 0, 0); + gopcodet(PSTORE, arg->type, arg->nname); + } + + i = 0; + arg = structfirst(&save, getinarg(t)); + while(arg != N) { + fnparam(t, 2, i); + gopcodet(PLOADI, arg->type, arg->nname); + + arg = structnext(&save); + i++; + } +} + +void +cgen_ret(Node *n) +{ + Node *arg, *a, *f; + Iter save; + + arg = listfirst(&save, &n->left); // expr list + a = getoutargx(curfn->type); + f = a->type; + for(;;) { + if(arg == N) + break; + if(f->etype != TFIELD) + fatal("cgen_ret: not field"); + if(arg->addable && !needconvert(f->type, arg->type)) { + gopcode(PLOAD, PTADDR, a->nname); + gopcode(PADDO, PTADDR, f->nname); + gopcodet(PSTOREI, arg->type, arg); + } else { + cgen(arg); + genconv(f, arg); + gopcode(PLOAD, PTADDR, a->nname); + gopcode(PADDO, PTADDR, f->nname); + gopcodet(PSTOREI, f->type, N); + } + arg = listnext(&save); + f = f->down; + } + gopcodet(PRETURN, N, N); +} + +void +cgen_call(Node *n, int toss) +{ + Node *t, *at, *ae, *sn; + Iter save; + int i; + + /* + * open a block + */ + gopcodet(PCALL1, N, n->left); + + /* + * prepare the input args + */ + t = n->left->type; + if(t->etype == TPTR) + t = t->type; + + at = *getinarg(t); // parameter struct + sn = at->nname; // in arg structure name + + at = at->type; // parameter fields + ae = listfirst(&save, &n->right); // expr list + + for(i=0; i<t->intuple; i++) { + if(ae == N) + fatal("cgen_call: tupleness"); + + if(ae->addable && !needconvert(at->type, ae->type)) { + gopcode(PADDR, PTADDR, sn); + gopcode(PADDO, PTADDR, at->nname); + gopcodet(PSTOREI, at->type, ae); + } else { + cgen(ae); + genconv(at, ae); + gopcode(PADDR, PTADDR, sn); + gopcode(PADDO, PTADDR, at->nname); + gopcodet(PSTOREI, at->type, N); + } + ae = listnext(&save); + at = at->down; + } + + /* + * call the function + */ + switch(n->op) { + default: + fatal("cgen_call: %O", n->op); + + case OCALL: + gopcodet(PCALL2, N, n->left); + break; + + case OCALLPTR: + cgen(n->left); + gopcodet(PCALLI2, N, n->left); + break; + + case OCALLMETH: + cgen(n->left); + gopcodet(PCALLM2, N, n->left); + break; + + case OCALLINTER: + cgen(n->left); + gopcodet(PCALLF2, N, n->left); + break; + } + + /* + * toss the output args + */ + if(toss) { + gopcodet(PCALL3, N, n->left); + return; + } +} + +void +cgen_callret(Node *n, Node *mas) +{ + Node *t, *at, *ae, *sn; + Iter save; + int i; + + t = n->left->type; + if(t->etype == TPTR) + t = t->type; + + at = *getoutarg(t); // parameter struct + sn = at->nname; // out arg structure name + at = at->type; // parameter fields + + // call w single return val to a register + if(mas == N) { + gopcode(PADDR, PTADDR, sn); + gopcode(PADDO, PTADDR, at->nname); + gopcodet(PLOADI, at->type, N); + gopcodet(PCALL3, N, N); + return; + } + + // call w multiple values to lval list + ae = listfirst(&save, &mas); // expr list + for(i=0; i<t->outtuple; i++) { + if(ae == N) + fatal("cgen_callret: output arguments do not match"); + + if(ae->addable) { + gopcode(PADDR, PTADDR, sn); + gopcode(PADDO, PTADDR, at->nname); + gopcodet(PLOADI, at->type, ae); + } else { + agen(ae); + gopcode(PADDR, PTADDR, sn); + gopcode(PADDO, PTADDR, at->nname); + gopcodet(PLOADI, at->type, N); + } + + ae = listnext(&save); + at = at->down; + } + + gopcodet(PCALL3, N, N); +} + +void +genprint(Node *n) +{ + Node *arg; + Iter save; + + arg = listfirst(&save, &n); + while(arg != N) { + cgen(arg); + gopcodet(PPRINT, arg->type, N); + arg = listnext(&save); + } +} + +int +needconvert(Node *tl, Node *tr) +{ + if(isinter(tl)) { + if(isptrto(tr, TSTRUCT)) + return 1; + if(isinter(tr)) + return 1; + return 0; + } + if(isptrto(tl, TSTRUCT)) + if(isinter(tr)) + return 1; + return 0; +} + +void +genconv(Node *l, Node *r) +{ + Node *tl, *tr; + + tl = l->type; + tr = r->type; + if(needconvert(tl, tr)) + gopcode(PCONV, PTNIL, nod(OCONV, tl, tr)); +} + +void +genindex(Node *n) +{ + gopcode(PINDEX, n->right->type->etype, n); +} + +int +optopop(int op) +{ + int a; + + switch(op) { + default: + fatal("optopop: unknown op %O\n", op); + + case OMINUS: a = PMINUS; break; + case OCOM: a = PCOM; break; + case OAND: a = PAND; break; + case OOR: a = POR; break; + case OXOR: a = PXOR; break; + case OADD: a = PADD; break; + case OMUL: a = PMUL; break; + case OMOD: a = PMOD; break; + case OSUB: a = PSUB; break; + case ODIV: a = PDIV; break; + case OLSH: a = PLSH; break; + case ORSH: a = PRSH; break; + case OCAT: a = PCAT; break; + } + return a; +} |