Commit eb1774fa authored by Russ Cox's avatar Russ Cox

cmd/gc: factor newly-portable code into gc directory

This isn't everything, but it's a start.
Still producing bit-identical compiler output.

The semantics of the old back ends is preserved,
even when they are probably buggy.
There are some TODOs in gc/gsubr.c to
remove special cases to preserve bugs in 5g and 8g.

Change-Id: I28ae295fbfc94ef9df43e13ab96bd6fc2f194bc4
Reviewed-on: https://go-review.googlesource.com/3802Reviewed-by: default avatarAustin Clements <austin@google.com>
parent 81a3f291
......@@ -277,6 +277,9 @@ enum {
A_ARCHSPECIFIC, // first architecture-specific opcode value
};
void nopout(Prog*);
void nocache(Prog*);
// prevent incompatible type signatures between liblink and 8l on Plan 9
#pragma incomplete struct Section
......
......@@ -46,8 +46,9 @@ main(int argc, char **argv)
arch.thestring = thestring;
arch.thelinkarch = thelinkarch;
arch.typedefs = typedefs;
arch.REGSP = REGSP;
arch.REGCTXT = REGCTXT;
arch.MAXWIDTH = MAXWIDTH;
arch.afunclit = afunclit;
arch.anyregalloc = anyregalloc;
arch.betypeinit = betypeinit;
arch.bgen = bgen;
......@@ -57,37 +58,15 @@ main(int argc, char **argv)
arch.cgen_callinter = cgen_callinter;
arch.cgen_ret = cgen_ret;
arch.clearfat = clearfat;
arch.clearp = clearp;
arch.defframe = defframe;
arch.dgostringptr = dgostringptr;
arch.dgostrlitptr = dgostrlitptr;
arch.dsname = dsname;
arch.dsymptr = dsymptr;
arch.dumpdata = dumpdata;
arch.dumpit = dumpit;
arch.excise = excise;
arch.expandchecks = expandchecks;
arch.fixautoused = fixautoused;
arch.gclean = gclean;
arch.gdata = gdata;
arch.gdatacomplex = gdatacomplex;
arch.gdatastring = gdatastring;
arch.ggloblnod = ggloblnod;
arch.ggloblsym = ggloblsym;
arch.ginit = ginit;
arch.gins = gins;
arch.ginscall = ginscall;
arch.gjmp = gjmp;
arch.gtrack = gtrack;
arch.gused = gused;
arch.igen = igen;
arch.isfat = isfat;
arch.linkarchinit = linkarchinit;
arch.markautoused = markautoused;
arch.naddr = naddr;
arch.newplist = newplist;
arch.nodarg = nodarg;
arch.patch = patch;
arch.proginfo = proginfo;
arch.regalloc = regalloc;
arch.regfree = regfree;
......@@ -96,7 +75,6 @@ main(int argc, char **argv)
arch.sameaddr = sameaddr;
arch.smallindir = smallindir;
arch.stackaddr = stackaddr;
arch.unpatch = unpatch;
gcmain(argc, argv);
}
......@@ -17,10 +17,7 @@ enum
REGALLOC_FMAX = FREGEXT,
};
EXTERN int32 dynloc;
EXTERN uchar reg[REGALLOC_FMAX+1];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
extern long unmappedzero;
/*
......
......@@ -117,52 +117,6 @@ appendpp(Prog *p, int as, int ftype, int freg, int32 foffset, int ttype, int tre
return q;
}
// Sweep the prog list to mark any used nodes.
void
markautoused(Prog* p)
{
for (; p; p = p->link) {
if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
continue;
if (p->from.node)
((Node*)(p->from.node))->used = 1;
if (p->to.node)
((Node*)(p->to.node))->used = 1;
}
}
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
void
fixautoused(Prog* p)
{
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
nopout(p);
continue;
}
if (p->from.name == NAME_AUTO && p->from.node)
p->from.offset += ((Node*)(p->from.node))->stkdelta;
if (p->to.name == NAME_AUTO && p->to.node)
p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
}
/*
* generate:
* call f
......@@ -176,7 +130,7 @@ void
ginscall(Node *f, int proc)
{
Prog *p;
Node n1, r, r1, con;
Node r, r1, con;
int32 extra;
if(f->type != T) {
......@@ -238,10 +192,7 @@ ginscall(Node *f, int proc)
p->to.reg = REGSP;
p->to.offset = 4;
memset(&n1, 0, sizeof n1);
n1.op = OADDR;
n1.left = f;
gins(AMOVW, &n1, &r);
gins(AMOVW, f, &r);
p = gins(AMOVW, &r, N);
p->to.type = TYPE_MEM;
p->to.reg = REGSP;
......@@ -615,18 +566,6 @@ ret:
;
}
int
samereg(Node *a, Node *b)
{
if(a->op != OREGISTER)
return 0;
if(b->op != OREGISTER)
return 0;
if(a->val.u.reg != b->val.u.reg)
return 0;
return 1;
}
/*
* generate high multiply
* res = (nl * nr) >> wordsize
......
// Derived from Inferno utils/5c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *sym, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.etype = TINT32;
p->from.offset = off;
p->from.reg = 0;
p->from.sym = linksym(sym);
p->from3.type = TYPE_CONST;
p->from3.offset = n;
p->to.type = TYPE_SCONST;
p->to.name = NAME_NONE;
p->to.reg = 0;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->etype = TINT32;
a->offset = widthptr+4; // skip header
a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->etype = TSTRING;
a->offset = 0; // header
a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
vlong v;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
p->from3.type = TYPE_CONST;
p->from3.offset = 4;
p = gins(ADATA, nam, nodintconst(v>>32));
p->from3.type = TYPE_CONST;
p->from3.offset = 4;
p->from.offset += 4;
return;
}
p = gins(ADATA, nam, nr);
p->from3.type = TYPE_CONST;
p->from3.offset = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->from.offset += w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->from3.type = TYPE_CONST;
p->from3.offset = types[tptr]->width;
p->to.type = TYPE_CONST;
p->to.etype = TINT32;
//print("%P\n", p);
nodconst(&nod1, types[TINT32], sval->len);
p = gins(ADATA, nam, &nod1);
p->from3.type = TYPE_CONST;
p->from3.offset = types[TINT32]->width;
p->from.offset += types[tptr]->width;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = TYPE_CONST;
p->to.etype = TINT32;
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datagostring(lit, &p->to);
p->to.type = TYPE_CONST;
p->to.etype = TINT32;
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
p->to.type = TYPE_ADDR;
p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
p->scond = zprog.scond;
p->from = zprog.from;
p->to = zprog.to;
p->reg = zprog.reg;
}
This diff is collapsed.
......@@ -725,7 +725,7 @@ mkvar(Reg *r, Adr *a)
flag = 0;
switch(t) {
default:
print("type %d %d %D\n", t, a->name, a);
print("mkvar: type %d %d %D\n", t, a->name, a);
goto none;
case TYPE_NONE:
......
......@@ -91,6 +91,7 @@ enum
REGG = REGEXT-0,
REGM = REGEXT-1,
REGCTXT = REG_R7,
REGTMP = REG_R11,
REGSP = REG_R13,
REGLINK = REG_R14,
......
......@@ -69,8 +69,9 @@ main(int argc, char **argv)
arch.thestring = thestring;
arch.thelinkarch = thelinkarch;
arch.typedefs = typedefs;
arch.REGSP = REGSP;
arch.REGCTXT = REGCTXT;
arch.MAXWIDTH = MAXWIDTH;
arch.afunclit = afunclit;
arch.anyregalloc = anyregalloc;
arch.betypeinit = betypeinit;
arch.bgen = bgen;
......@@ -80,37 +81,15 @@ main(int argc, char **argv)
arch.cgen_callinter = cgen_callinter;
arch.cgen_ret = cgen_ret;
arch.clearfat = clearfat;
arch.clearp = clearp;
arch.defframe = defframe;
arch.dgostringptr = dgostringptr;
arch.dgostrlitptr = dgostrlitptr;
arch.dsname = dsname;
arch.dsymptr = dsymptr;
arch.dumpdata = dumpdata;
arch.dumpit = dumpit;
arch.excise = excise;
arch.expandchecks = expandchecks;
arch.fixautoused = fixautoused;
arch.gclean = gclean;
arch.gdata = gdata;
arch.gdatacomplex = gdatacomplex;
arch.gdatastring = gdatastring;
arch.ggloblnod = ggloblnod;
arch.ggloblsym = ggloblsym;
arch.ginit = ginit;
arch.gins = gins;
arch.ginscall = ginscall;
arch.gjmp = gjmp;
arch.gtrack = gtrack;
arch.gused = gused;
arch.igen = igen;
arch.isfat = isfat;
arch.linkarchinit = linkarchinit;
arch.markautoused = markautoused;
arch.naddr = naddr;
arch.newplist = newplist;
arch.nodarg = nodarg;
arch.patch = patch;
arch.proginfo = proginfo;
arch.regalloc = regalloc;
arch.regfree = regfree;
......@@ -119,7 +98,6 @@ main(int argc, char **argv)
arch.sameaddr = sameaddr;
arch.smallindir = smallindir;
arch.stackaddr = stackaddr;
arch.unpatch = unpatch;
gcmain(argc, argv);
}
......@@ -9,10 +9,7 @@
#include "../gc/go.h"
#include "../6l/6.out.h"
EXTERN int32 dynloc;
EXTERN uchar reg[MAXREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Node* panicdiv;
extern vlong unmappedzero;
extern int addptr;
......
......@@ -115,52 +115,6 @@ appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int tre
return q;
}
// Sweep the prog list to mark any used nodes.
void
markautoused(Prog* p)
{
for (; p; p = p->link) {
if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
continue;
if (p->from.node)
((Node*)(p->from.node))->used = 1;
if (p->to.node)
((Node*)(p->to.node))->used = 1;
}
}
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
void
fixautoused(Prog *p)
{
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
nopout(p);
continue;
}
if (p->from.name == NAME_AUTO && p->from.node)
p->from.offset += ((Node*)(p->from.node))->stkdelta;
if (p->to.name == NAME_AUTO && p->to.node)
p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
}
/*
* generate:
* call f
......@@ -616,20 +570,6 @@ ret:
;
}
int
samereg(Node *a, Node *b)
{
if(a == N || b == N)
return 0;
if(a->op != OREGISTER)
return 0;
if(b->op != OREGISTER)
return 0;
if(a->val.u.reg != b->val.u.reg)
return 0;
return 1;
}
/*
* generate division.
* generates one of:
......
// Derived from Inferno utils/6c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.offset = off;
p->from.sym = linksym(s);
p->from3.type = TYPE_CONST;
p->from3.offset = n;
p->to.type = TYPE_SCONST;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = widthptr+widthint; // skip header
a->etype = simtype[TINT];
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
a->etype = TSTRING;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
p = gins(ADATA, nam, nr);
p->from3.type = TYPE_CONST;
p->from3.offset = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->from.offset += w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->from3.type = TYPE_CONST;
p->from3.offset = types[tptr]->width;
p->to.type = TYPE_ADDR;
//print("%P\n", p);
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
p->from3.type = TYPE_CONST;
p->from3.offset = widthint;
p->from.offset += widthptr;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datagostring(lit, &p->to);
p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
p->to.type = TYPE_ADDR;
p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
p->from = zprog.from;
p->to = zprog.to;
}
This diff is collapsed.
......@@ -834,6 +834,7 @@ enum
FREGRET = REG_X0,
REGSP = REG_SP,
REGTMP = REG_DI,
REGCTXT = REG_DX,
REGEXT = REG_R15, /* compiler allocates external registers R15 down */
FREGMIN = REG_X0+5, /* first register variable */
FREGEXT = REG_X0+15, /* first external register */
......
......@@ -46,8 +46,9 @@ main(int argc, char **argv)
arch.thestring = thestring;
arch.thelinkarch = thelinkarch;
arch.typedefs = typedefs;
arch.REGSP = REGSP;
arch.REGCTXT = REGCTXT;
arch.MAXWIDTH = MAXWIDTH;
arch.afunclit = afunclit;
arch.anyregalloc = anyregalloc;
arch.betypeinit = betypeinit;
arch.bgen = bgen;
......@@ -57,37 +58,15 @@ main(int argc, char **argv)
arch.cgen_callinter = cgen_callinter;
arch.cgen_ret = cgen_ret;
arch.clearfat = clearfat;
arch.clearp = clearp;
arch.defframe = defframe;
arch.dgostringptr = dgostringptr;
arch.dgostrlitptr = dgostrlitptr;
arch.dsname = dsname;
arch.dsymptr = dsymptr;
arch.dumpdata = dumpdata;
arch.dumpit = dumpit;
arch.excise = excise;
arch.expandchecks = expandchecks;
arch.fixautoused = fixautoused;
arch.gclean = gclean;
arch.gdata = gdata;
arch.gdatacomplex = gdatacomplex;
arch.gdatastring = gdatastring;
arch.ggloblnod = ggloblnod;
arch.ggloblsym = ggloblsym;
arch.ginit = ginit;
arch.gins = gins;
arch.ginscall = ginscall;
arch.gjmp = gjmp;
arch.gtrack = gtrack;
arch.gused = gused;
arch.igen = igen;
arch.isfat = isfat;
arch.linkarchinit = linkarchinit;
arch.markautoused = markautoused;
arch.naddr = naddr;
arch.newplist = newplist;
arch.nodarg = nodarg;
arch.patch = patch;
arch.proginfo = proginfo;
arch.regalloc = regalloc;
arch.regfree = regfree;
......@@ -96,7 +75,6 @@ main(int argc, char **argv)
arch.sameaddr = sameaddr;
arch.smallindir = smallindir;
arch.stackaddr = stackaddr;
arch.unpatch = unpatch;
gcmain(argc, argv);
}
......@@ -17,10 +17,7 @@ enum
Fpop2 = 1<<2,
};
EXTERN int32 dynloc;
EXTERN uchar reg[MAXREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Node* panicdiv;
extern uint32 unmappedzero;
......
......@@ -106,52 +106,6 @@ appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int tre
return q;
}
// Sweep the prog list to mark any used nodes.
void
markautoused(Prog* p)
{
for (; p; p = p->link) {
if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
continue;
if (p->from.node)
((Node*)(p->from.node))->used = 1;
if (p->to.node)
((Node*)(p->to.node))->used = 1;
}
}
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
void
fixautoused(Prog* p)
{
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
nopout(p);
continue;
}
if (p->from.type == TYPE_MEM && p->from.name == NAME_AUTO && p->from.node)
p->from.offset += ((Node*)(p->from.node))->stkdelta;
if (p->to.type == TYPE_MEM && p->to.name == NAME_AUTO && p->to.node)
p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
}
void
clearfat(Node *nl)
{
......@@ -660,18 +614,6 @@ ret:
;
}
int
samereg(Node *a, Node *b)
{
if(a->op != OREGISTER)
return 0;
if(b->op != OREGISTER)
return 0;
if(a->val.u.reg != b->val.u.reg)
return 0;
return 1;
}
/*
* generate division.
* caller must set:
......
// Derived from Inferno utils/8c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/8c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = n;
p->from.sym = linksym(s);
p->to.type = TYPE_SCONST;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = widthptr+4; // skip header
a->etype = TINT32;
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
a->etype = TSTRING;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
vlong v;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
p->from3.type = TYPE_CONST;
p->from3.offset = 4;
p = gins(ADATA, nam, nodintconst(v>>32));
p->from3.type = TYPE_CONST;
p->from3.offset = 4;
p->from.offset += 4;
return;
}
p = gins(ADATA, nam, nr);
p->from3.type = TYPE_CONST;
p->from3.offset = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->from.offset += w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->from3.type = TYPE_CONST;
p->from3.offset = types[tptr]->width;
p->to.type = TYPE_ADDR;
//print("%P\n", p);
nodconst(&nod1, types[TINT32], sval->len);
p = gins(ADATA, nam, &nod1);
p->from3.type = TYPE_CONST;
p->from3.offset = types[TINT32]->width;
p->from.offset += types[tptr]->width;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = TYPE_ADDR;
p->to.etype = TINT32;
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datagostring(lit, &p->to);
p->to.type = TYPE_ADDR;
p->to.etype = TINT32;
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
p->to.type = TYPE_ADDR;
p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
p->from = zprog.from;
p->to = zprog.to;
}
This diff is collapsed.
......@@ -634,6 +634,7 @@ enum
FREGRET = REG_F0,
REGSP = REG_SP,
REGTMP = REG_DI,
REGCTXT = REG_DX,
};
/*
......
......@@ -53,8 +53,9 @@ main(int argc, char **argv)
arch.thestring = thestring;
arch.thelinkarch = thelinkarch;
arch.typedefs = typedefs;
arch.REGSP = REGSP;
arch.REGCTXT = REGCTXT;
arch.MAXWIDTH = MAXWIDTH;
arch.afunclit = afunclit;
arch.anyregalloc = anyregalloc;
arch.betypeinit = betypeinit;
arch.bgen = bgen;
......@@ -64,37 +65,15 @@ main(int argc, char **argv)
arch.cgen_callinter = cgen_callinter;
arch.cgen_ret = cgen_ret;
arch.clearfat = clearfat;
arch.clearp = clearp;
arch.defframe = defframe;
arch.dgostringptr = dgostringptr;
arch.dgostrlitptr = dgostrlitptr;
arch.dsname = dsname;
arch.dsymptr = dsymptr;
arch.dumpdata = dumpdata;
arch.dumpit = dumpit;
arch.excise = excise;
arch.expandchecks = expandchecks;
arch.fixautoused = fixautoused;
arch.gclean = gclean;
arch.gdata = gdata;
arch.gdatacomplex = gdatacomplex;
arch.gdatastring = gdatastring;
arch.ggloblnod = ggloblnod;
arch.ggloblsym = ggloblsym;
arch.ginit = ginit;
arch.gins = gins;
arch.ginscall = ginscall;
arch.gjmp = gjmp;
arch.gtrack = gtrack;
arch.gused = gused;
arch.igen = igen;
arch.isfat = isfat;
arch.linkarchinit = linkarchinit;
arch.markautoused = markautoused;
arch.naddr = naddr;
arch.newplist = newplist;
arch.nodarg = nodarg;
arch.patch = patch;
arch.proginfo = proginfo;
arch.regalloc = regalloc;
arch.regfree = regfree;
......@@ -103,7 +82,6 @@ main(int argc, char **argv)
arch.sameaddr = sameaddr;
arch.smallindir = smallindir;
arch.stackaddr = stackaddr;
arch.unpatch = unpatch;
gcmain(argc, argv);
}
......@@ -12,10 +12,7 @@
// TODO(minux): Remove when no longer used.
#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
EXTERN int32 dynloc;
EXTERN uchar reg[NREG+NFREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Node* panicdiv;
extern vlong unmappedzero;
......
......@@ -113,51 +113,6 @@ appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int tre
return q;
}
// Sweep the prog list to mark any used nodes.
void
markautoused(Prog *p)
{
for (; p; p = p->link) {
if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
continue;
if (p->from.node)
((Node*)(p->from.node))->used = 1;
if (p->to.node)
((Node*)(p->to.node))->used = 1;
}
}
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
void
fixautoused(Prog *p)
{
Prog **lp;
for (lp=&p; (p=*lp) != P; ) {
if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
*lp = p->link;
continue;
}
if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
// VARDEFs are interspersed with other code, and a jump might be using the
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
// the no-ops.
nopout(p);
continue;
}
if (p->from.name == NAME_AUTO && p->from.node)
p->from.offset += ((Node*)(p->from.node))->stkdelta;
if (p->to.name == NAME_AUTO && p->to.node)
p->to.offset += ((Node*)(p->to.node))->stkdelta;
lp = &p->link;
}
}
/*
* generate: BL reg, f
* where both reg and f are registers.
......@@ -226,7 +181,7 @@ ginscall(Node *f, int proc)
gins(AUNDEF, N, N);
break;
}
nodreg(&reg, types[tptr], REGENV);
nodreg(&reg, types[tptr], REGCTXT);
nodreg(&r1, types[tptr], REG_R3);
gmove(f, &reg);
reg.op = OINDREG;
......@@ -494,20 +449,6 @@ cgen_asop(Node *n)
fatal("cgen_asop"); // no longer used
}
int
samereg(Node *a, Node *b)
{
if(a == N || b == N)
return 0;
if(a->op != OREGISTER)
return 0;
if(b->op != OREGISTER)
return 0;
if(a->val.u.reg != b->val.u.reg)
return 0;
return 1;
}
/*
* generate division.
* generates one of:
......
// Derived from Inferno utils/6c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.offset = off;
p->from.sym = linksym(s);
p->from3.type = TYPE_CONST;
p->from3.offset = n;
p->to.type = TYPE_SCONST;
p->to.name = NAME_NONE;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->etype = simtype[TINT];
a->offset = widthptr+widthint; // skip header
a->reg = 0;
a->sym = linksym(sym);
a->node = sym->def;
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = TYPE_MEM;
a->name = NAME_EXTERN;
a->sym = linksym(sym);
a->reg = 0;
a->node = sym->def;
a->offset = 0; // header
a->etype = TSTRING;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
p = gins(ADATA, nam, nr);
p->from3.type = TYPE_CONST;
p->from3.offset = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->from3.type = TYPE_CONST;
p->from3.offset = w;
p->from.offset += w;
p->to.type = TYPE_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->from3.type = TYPE_CONST;
p->from3.offset = types[tptr]->width;
p->to.type = TYPE_ADDR;
p->to.etype = simtype[tptr];
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
p->from3.type = TYPE_CONST;
p->from3.offset = widthint;
p->from.offset += widthptr;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = TYPE_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
datagostring(lit, &p->to);
p->to.type = TYPE_ADDR;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = TYPE_MEM;
p->from.name = NAME_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->from3.type = TYPE_CONST;
p->from3.offset = widthptr;
p->to.type = TYPE_ADDR;
p->to.name = NAME_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
p->from = zprog.from;
p->from3 = zprog.from3;
p->reg = zprog.reg;
p->to = zprog.to;
}
This diff is collapsed.
......@@ -204,7 +204,7 @@ enum
REGRT1 = REG_R3, /* reserved for runtime, duffzero and duffcopy */
REGRT2 = REG_R4, /* reserved for runtime, duffcopy */
REGMIN = REG_R7, /* register variables allocated from here to REGMAX */
REGENV = REG_R11, /* environment for closures */
REGCTXT = REG_R11, /* context for closures */
REGTLS = REG_R13, /* C ABI TLS base pointer */
REGMAX = REG_R27,
REGEXT = REG_R30, /* external registers allocated from here down */
......
......@@ -304,8 +304,8 @@ gen(Node *n)
// if there are pending gotos, resolve them all to the current pc.
for(p1=lab->gotopc; p1; p1=p2) {
p2 = arch.unpatch(p1);
arch.patch(p1, pc);
p2 = unpatch(p1);
patch(p1, pc);
}
lab->gotopc = P;
if(lab->labelpc == P)
......@@ -332,9 +332,9 @@ gen(Node *n)
// of the label in the OLABEL case above.)
lab = newlab(n);
if(lab->labelpc != P)
arch.gjmp(lab->labelpc);
gjmp(lab->labelpc);
else
lab->gotopc = arch.gjmp(lab->gotopc);
lab->gotopc = gjmp(lab->gotopc);
break;
case OBREAK:
......@@ -349,14 +349,14 @@ gen(Node *n)
yyerror("invalid break label %S", n->left->sym);
break;
}
arch.gjmp(lab->breakpc);
gjmp(lab->breakpc);
break;
}
if(breakpc == P) {
yyerror("break is not in a loop");
break;
}
arch.gjmp(breakpc);
gjmp(breakpc);
break;
case OCONTINUE:
......@@ -371,20 +371,20 @@ gen(Node *n)
yyerror("invalid continue label %S", n->left->sym);
break;
}
arch.gjmp(lab->continpc);
gjmp(lab->continpc);
break;
}
if(continpc == P) {
yyerror("continue is not in a loop");
break;
}
arch.gjmp(continpc);
gjmp(continpc);
break;
case OFOR:
sbreak = breakpc;
p1 = arch.gjmp(P); // goto test
breakpc = arch.gjmp(P); // break: goto done
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
scontin = continpc;
continpc = pc;
......@@ -394,11 +394,11 @@ gen(Node *n)
lab->continpc = continpc;
}
gen(n->nincr); // contin: incr
arch.patch(p1, pc); // test:
patch(p1, pc); // test:
arch.bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
genlist(n->nbody); // body
arch.gjmp(continpc);
arch.patch(breakpc, pc); // done:
gjmp(continpc);
patch(breakpc, pc); // done:
continpc = scontin;
breakpc = sbreak;
if(lab) {
......@@ -408,29 +408,29 @@ gen(Node *n)
break;
case OIF:
p1 = arch.gjmp(P); // goto test
p2 = arch.gjmp(P); // p2: goto else
arch.patch(p1, pc); // test:
p1 = gjmp(P); // goto test
p2 = gjmp(P); // p2: goto else
patch(p1, pc); // test:
arch.bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
genlist(n->nbody); // then
p3 = arch.gjmp(P); // goto done
arch.patch(p2, pc); // else:
p3 = gjmp(P); // goto done
patch(p2, pc); // else:
genlist(n->nelse); // else
arch.patch(p3, pc); // done:
patch(p3, pc); // done:
break;
case OSWITCH:
sbreak = breakpc;
p1 = arch.gjmp(P); // goto test
breakpc = arch.gjmp(P); // break: goto done
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
arch.patch(p1, pc); // test:
patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
arch.patch(breakpc, pc); // done:
patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
......@@ -438,16 +438,16 @@ gen(Node *n)
case OSELECT:
sbreak = breakpc;
p1 = arch.gjmp(P); // goto test
breakpc = arch.gjmp(P); // break: goto done
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
arch.patch(p1, pc); // test:
patch(p1, pc); // test:
genlist(n->nbody); // select() body
arch.patch(breakpc, pc); // done:
patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
......@@ -601,7 +601,7 @@ cgen_discard(Node *nr)
switch(nr->op) {
case ONAME:
if(!(nr->class & PHEAP) && nr->class != PEXTERN && nr->class != PFUNC && nr->class != PPARAMREF)
arch.gused(nr);
gused(nr);
break;
// unary
......@@ -643,7 +643,7 @@ cgen_discard(Node *nr)
default:
tempname(&tmp, nr->type);
cgen_as(&tmp, nr);
arch.gused(&tmp);
gused(&tmp);
}
}
......@@ -739,7 +739,7 @@ cgen_as(Node *nl, Node *nr)
tl = nl->type;
if(tl == T)
return;
if(arch.isfat(tl)) {
if(isfat(tl)) {
if(nl->op == ONAME)
gvardef(nl);
arch.clearfat(nl);
......@@ -857,9 +857,9 @@ cgen_slice(Node *n, Node *res)
// In essence we are replacing x[i:j:k] where i == j == k
// or x[i:j] where i == j == cap(x) with x[0:0:0].
if(offs != N) {
p1 = arch.gjmp(P);
p2 = arch.gjmp(P);
arch.patch(p1, pc);
p1 = gjmp(P);
p2 = gjmp(P);
patch(p1, pc);
nodconst(&con, tmpcap->type, 0);
cmp = nod(OEQ, tmpcap, &con);
......@@ -870,7 +870,7 @@ cgen_slice(Node *n, Node *res)
typecheck(&add, Erv);
arch.cgen(add, base);
arch.patch(p2, pc);
patch(p2, pc);
}
// dst.array = src.array [ + lo *width ]
......
......@@ -1514,7 +1514,6 @@ void gvarkill(Node*);
void movelarge(NodeList*);
void liveness(Node*, Prog*, Sym*, Sym*);
void twobitwalktype1(Type*, vlong*, Bvec*);
void nopout(Prog*);
#pragma varargck type "B" Mpint*
#pragma varargck type "E" int
......@@ -1659,9 +1658,10 @@ struct Arch
LinkArch *thelinkarch;
Typedef *typedefs;
int REGSP;
int REGCTXT;
vlong MAXWIDTH;
void (*afunclit)(Addr*, Node*);
int (*anyregalloc)(void);
void (*betypeinit)(void);
void (*bgen)(Node*, int, int, Prog*);
......@@ -1671,37 +1671,15 @@ struct Arch
void (*cgen_callinter)(Node*, Node*, int);
void (*cgen_ret)(Node*);
void (*clearfat)(Node*);
void (*clearp)(Prog*);
void (*defframe)(Prog*);
int (*dgostringptr)(Sym*, int, char*);
int (*dgostrlitptr)(Sym*, int, Strlit*);
int (*dsname)(Sym*, int, char*, int);
int (*dsymptr)(Sym*, int, Sym*, int);
void (*dumpdata)(void);
void (*dumpit)(char*, Flow*, int);
void (*excise)(Flow*);
void (*expandchecks)(Prog*);
void (*fixautoused)(Prog*);
void (*gclean)(void);
void (*gdata)(Node*, Node*, int);
void (*gdatacomplex)(Node*, Mpcplx*);
void (*gdatastring)(Node*, Strlit*);
void (*ggloblnod)(Node*);
void (*ggloblsym)(Sym*, int32, int8);
void (*ginit)(void);
Prog* (*gins)(int, Node*, Node*);
void (*ginscall)(Node*, int);
Prog* (*gjmp)(Prog*);
void (*gtrack)(Sym*);
void (*gused)(Node*);
void (*igen)(Node*, Node*, Node*);
int (*isfat)(Type*);
void (*linkarchinit)(void);
void (*markautoused)(Prog*);
void (*naddr)(Node*, Addr*, int);
Plist* (*newplist)(void);
Node* (*nodarg)(Type*, int);
void (*patch)(Prog*, Prog*);
void (*proginfo)(ProgInfo*, Prog*);
void (*regalloc)(Node*, Type*, Node*);
void (*regfree)(Node*);
......@@ -1710,9 +1688,38 @@ struct Arch
int (*sameaddr)(Addr*, Addr*);
int (*smallindir)(Addr*, Addr*);
int (*stackaddr)(Addr*);
Prog* (*unpatch)(Prog*);
};
void afunclit(Addr*, Node*);
void clearp(Prog*);
void defframe(Prog*);
int dgostringptr(Sym*, int, char*);
int dgostrlitptr(Sym*, int, Strlit*);
int dsname(Sym*, int, char*, int);
int dsymptr(Sym*, int, Sym*, int);
void dumpdata(void);
void fixautoused(Prog*);
void gdata(Node*, Node*, int);
void gdatacomplex(Node*, Mpcplx*);
void gdatastring(Node*, Strlit*);
void ggloblnod(Node*);
void ggloblsym(Sym*, int32, int8);
Prog* gjmp(Prog*);
void gtrack(Sym*);
void gused(Node*);
int isfat(Type*);
void markautoused(Prog*);
void naddr(Node*, Addr*, int);
Plist* newplist(void);
Node* nodarg(Type*, int);
void patch(Prog*, Prog*);
Prog* unpatch(Prog*);
void datagostring(Strlit *sval, Addr *a);
int ismem(Node*);
int samereg(Node*, Node*);
EXTERN int32 pcloc;
EXTERN Arch arch;
EXTERN Node *newproc;
......
This diff is collapsed.
This diff is collapsed.
......@@ -39,7 +39,7 @@ makefuncdatasym(char *namefmt, int64 funcdatakind)
// where a complete initialization (definition) of a variable begins.
// Since the liveness analysis can see initialization of single-word
// variables quite easy, gvardef is usually only called for multi-word
// or 'fat' variables, those satisfying arch.isfat(n->type).
// or 'fat' variables, those satisfying isfat(n->type).
// However, gvardef is also called when a non-fat variable is initialized
// via a block move; the only time this happens is when you have
// return f()
......@@ -223,7 +223,7 @@ compile(Node *fn)
continpc = P;
breakpc = P;
pl = arch.newplist();
pl = newplist();
pl->name = linksym(curfn->nname->sym);
setlineno(curfn);
......@@ -247,7 +247,7 @@ compile(Node *fn)
ptxt->from3.offset |= WRAPPER;
}
arch.afunclit(&ptxt->from, curfn->nname);
afunclit(&ptxt->from, curfn->nname);
arch.ginit();
......@@ -255,7 +255,7 @@ compile(Node *fn)
gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
for(t=curfn->paramfld; t; t=t->down)
arch.gtrack(tracksym(t->type));
gtrack(tracksym(t->type));
for(l=fn->dcl; l; l=l->next) {
n = l->n;
......@@ -325,7 +325,7 @@ compile(Node *fn)
gcsymdup(gcargs);
gcsymdup(gclocals);
arch.defframe(ptxt);
defframe(ptxt);
if(0)
frame(0);
......@@ -369,7 +369,7 @@ emitptrargsmap(void)
for(j = 0; j < bv->n; j += 32)
off = duint32(sym, off, bv->b[j/32]);
}
arch.ggloblsym(sym, off, RODATA);
ggloblsym(sym, off, RODATA);
free(bv);
}
......@@ -438,7 +438,7 @@ allocauto(Prog* ptxt)
if (ll->n->class == PAUTO)
ll->n->used = 0;
arch.markautoused(ptxt);
markautoused(ptxt);
listsort(&curfn->dcl, cmpstackvar);
......@@ -448,7 +448,7 @@ allocauto(Prog* ptxt)
if (n->class == PAUTO && n->op == ONAME && !n->used) {
// No locals used at all
curfn->dcl = nil;
arch.fixautoused(ptxt);
fixautoused(ptxt);
return;
}
......@@ -486,7 +486,7 @@ allocauto(Prog* ptxt)
stksize = rnd(stksize, widthreg);
stkptrsize = rnd(stkptrsize, widthreg);
arch.fixautoused(ptxt);
fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl; ll != nil; ll=ll->next) {
......
......@@ -744,7 +744,7 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
if(info.flags & (LeftRead | LeftAddr))
bvset(uevar, pos);
if(info.flags & LeftWrite)
if(from->node != nil && !arch.isfat(((Node*)(from->node))->type))
if(from->node != nil && !isfat(((Node*)(from->node))->type))
bvset(varkill, pos);
}
}
......@@ -780,7 +780,7 @@ Next:
if((info.flags & RightRead) || (info.flags & (RightAddr|RightWrite)) == RightAddr)
bvset(uevar, pos);
if(info.flags & RightWrite)
if(to->node != nil && (!arch.isfat(((Node*)(to->node))->type) || prog->as == AVARDEF))
if(to->node != nil && (!isfat(((Node*)(to->node))->type) || prog->as == AVARDEF))
bvset(varkill, pos);
}
}
......@@ -1218,7 +1218,7 @@ unlinkedprog(int as)
Prog *p;
p = mal(sizeof(*p));
arch.clearp(p);
clearp(p);
p->as = as;
return p;
}
......@@ -1235,8 +1235,8 @@ newpcdataprog(Prog *prog, int32 index)
nodconst(&to, types[TINT32], index);
pcdata = unlinkedprog(APCDATA);
pcdata->lineno = prog->lineno;
arch.naddr(&from, &pcdata->from, 0);
arch.naddr(&to, &pcdata->to, 0);
naddr(&from, &pcdata->from, 0);
naddr(&to, &pcdata->to, 0);
return pcdata;
}
......@@ -1932,7 +1932,7 @@ twobitwritesymbol(Array *arr, Sym *sym)
}
}
duint32(sym, 0, i); // number of bitmaps
arch.ggloblsym(sym, off, RODATA);
ggloblsym(sym, off, RODATA);
}
static void
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -96,6 +96,7 @@ static Optab optab[] =
{ ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0 },
{ ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0 },
{ ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0 },
{ ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0 }, // prediction hinted form, hint ignored
{ AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL },
{ ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0 },
......@@ -353,14 +354,6 @@ static uchar xcmp[C_GOK+1][C_GOK+1];
static LSym *deferreturn;
static void
nocache(Prog *p)
{
p->optab = 0;
p->from.class = 0;
p->to.class = 0;
}
/* size of a case statement including jump table */
static int32
casesz(Link *ctxt, Prog *p)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment