summaryrefslogtreecommitdiff
path: root/src/old/c/gen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/old/c/gen.c')
-rw-r--r--src/old/c/gen.c1186
1 files changed, 0 insertions, 1186 deletions
diff --git a/src/old/c/gen.c b/src/old/c/gen.c
deleted file mode 100644
index dc9e55038..000000000
--- a/src/old/c/gen.c
+++ /dev/null
@@ -1,1186 +0,0 @@
-// 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;
-}