cmd/gc contains symbol references into the back end dirs like 6g.
It also contains a few files that include the back end header files and
are compiled separately for each back end, despite being in cmd/gc.
cmd/gc also defines main, which makes at least one reverse symbol
reference unavoidable. (Otherwise you can't get into back-end code.)
This was all expedient, but it's too tightly coupled, especially for a
program written Go.
Make cmd/gc into a true library, letting the back end define main and
call into cmd/gc after making the necessary references available.
cmd/gc being a real library will ease the transition to Go.
Change-Id: I4fb9a0e2b11a32f1d024b3c56fc3bd9ee458842c
Reviewed-on: https://go-review.googlesource.com/3277
Reviewed-by: Rob Pike <r@golang.org>
zprog.from.name = D_NONE;
zprog.from.reg = NREG;
zprog.to = zprog.from;
+ arch.zprog = zprog;
listinit5();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.zprog = zprog;
+ arch.ACALL = ABL;
+ arch.ACHECKNIL = ACHECKNIL;
+ arch.ADATA = ADATA;
+ arch.AFUNCDATA = AFUNCDATA;
+ arch.AGLOBL = AGLOBL;
+ arch.AJMP = AB;
+ arch.ANAME = ANAME;
+ arch.ANOP = ANOP;
+ arch.APCDATA = APCDATA;
+ arch.ARET = ARET;
+ arch.ASIGNAME = ASIGNAME;
+ arch.ATEXT = ATEXT;
+ arch.ATYPE = ATYPE;
+ arch.AUNDEF = AUNDEF;
+ arch.AVARDEF = AVARDEF;
+ arch.AVARKILL = AVARKILL;
+ arch.D_AUTO = D_AUTO;
+ arch.D_BRANCH = D_BRANCH;
+ arch.D_NONE = D_NONE;
+ arch.D_PARAM = D_PARAM;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ 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;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
-EXTERN Node* throwreturn;
extern long unmappedzero;
/*
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+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 *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+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*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Register in middle (Prog.reg); only ever read.
- RegRead = 1<<12,
- CanRegRead = 1<<13,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<14,
- RightRead = 1<<15,
- RightWrite = 1<<16,
-
- // Instruction kinds
- Move = 1<<17, // straight move
- Conv = 1<<18, // size conversion
- Cjmp = 1<<19, // conditional jump
- Break = 1<<20, // breaks control flow (no fallthrough)
- Call = 1<<21, // function call
- Jump = 1<<22, // jump
- Skip = 1<<23, // data instruction
-};
-
void proginfo(ProgInfo*, Prog*);
// To allow use of AJMP and ACALL in ../gc/popt.c.
void
linkarchinit(void)
{
- if(strcmp(getgoarch(), "amd64p32") == 0)
+ if(strcmp(getgoarch(), "amd64p32") == 0) {
thelinkarch = &linkamd64p32;
+ arch.thelinkarch = thelinkarch;
+ thestring = "amd64p32";
+ arch.thestring = "amd64p32";
+ }
}
vlong MAXWIDTH = 1LL<<50;
zprog.from.index = D_NONE;
zprog.from.scale = 0;
zprog.to = zprog.from;
+ arch.zprog = zprog;
listinit6();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.zprog = zprog;
+ arch.ACALL = ACALL;
+ arch.ACHECKNIL = ACHECKNIL;
+ arch.ADATA = ADATA;
+ arch.AFUNCDATA = AFUNCDATA;
+ arch.AGLOBL = AGLOBL;
+ arch.AJMP = AJMP;
+ arch.ANAME = ANAME;
+ arch.ANOP = ANOP;
+ arch.APCDATA = APCDATA;
+ arch.ARET = ARET;
+ arch.ASIGNAME = ASIGNAME;
+ arch.ATEXT = ATEXT;
+ arch.ATYPE = ATYPE;
+ arch.AUNDEF = AUNDEF;
+ arch.AVARDEF = AVARDEF;
+ arch.AVARKILL = AVARKILL;
+ arch.D_AUTO = D_AUTO;
+ arch.D_BRANCH = D_BRANCH;
+ arch.D_NONE = D_NONE;
+ arch.D_PARAM = D_PARAM;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ 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;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern vlong unmappedzero;
extern int addptr;
extern int cmpptr;
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+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 *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+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*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint32 reguse; // registers implicitly used by this instruction
- uint32 regset; // registers implicitly set by this instruction
- uint32 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<12,
- RightRead = 1<<13,
- RightWrite = 1<<14,
-
- // Set, use, or kill of carry bit.
- // Kill means we never look at the carry bit after this kind of instruction.
- SetCarry = 1<<15,
- UseCarry = 1<<16,
- KillCarry = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-
- // Special cases for register use.
- ShiftCX = 1<<25, // possible shift by CX
- ImulAXDX = 1<<26, // possible multiply into DX:AX
-};
void proginfo(ProgInfo*, Prog*);
zprog.from.index = D_NONE;
zprog.from.scale = 0;
zprog.to = zprog.from;
+ arch.zprog = zprog;
listinit8();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.zprog = zprog;
+ arch.ACALL = ACALL;
+ arch.ACHECKNIL = ACHECKNIL;
+ arch.ADATA = ADATA;
+ arch.AFUNCDATA = AFUNCDATA;
+ arch.AGLOBL = AGLOBL;
+ arch.AJMP = AJMP;
+ arch.ANAME = ANAME;
+ arch.ANOP = ANOP;
+ arch.APCDATA = APCDATA;
+ arch.ARET = ARET;
+ arch.ASIGNAME = ASIGNAME;
+ arch.ATEXT = ATEXT;
+ arch.ATYPE = ATYPE;
+ arch.AUNDEF = AUNDEF;
+ arch.AVARDEF = AVARDEF;
+ arch.AVARKILL = AVARKILL;
+ arch.D_AUTO = D_AUTO;
+ arch.D_BRANCH = D_BRANCH;
+ arch.D_NONE = D_NONE;
+ arch.D_PARAM = D_PARAM;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ 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;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern uint32 unmappedzero;
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+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 *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+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*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint32 reguse; // registers implicitly used by this instruction
- uint32 regset; // registers implicitly set by this instruction
- uint32 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<12,
- RightRead = 1<<13,
- RightWrite = 1<<14,
-
- // Set, use, or kill of carry bit.
- // Kill means we never look at the carry bit after this kind of instruction.
- SetCarry = 1<<15,
- UseCarry = 1<<16,
- KillCarry = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-
- // Special cases for register use.
- ShiftCX = 1<<25, // possible shift by CX
- ImulAXDX = 1<<26, // possible multiply into DX:AX
-};
-
void proginfo(ProgInfo*, Prog*);
linkarchinit(void)
{
thestring = getgoarch();
+ arch.thestring = thestring;
if(strcmp(thestring, "ppc64le") == 0)
thelinkarch = &linkppc64le;
else
thelinkarch = &linkppc64;
+ arch.thelinkarch = thelinkarch;
}
vlong MAXWIDTH = 1LL<<50;
zprog.from.reg = NREG;
zprog.to = zprog.from;
zprog.from3 = zprog.from;
+ arch.zprog = zprog;
listinit9();
}
+
+void
+main(int argc, char **argv)
+{
+ arch.thechar = thechar;
+ arch.thestring = thestring;
+ arch.thelinkarch = thelinkarch;
+ arch.typedefs = typedefs;
+ arch.zprog = zprog;
+ arch.ACALL = ABL;
+ arch.ACHECKNIL = ACHECKNIL;
+ arch.ADATA = ADATA;
+ arch.AFUNCDATA = AFUNCDATA;
+ arch.AGLOBL = AGLOBL;
+ arch.AJMP = ABR;
+ arch.ANAME = ANAME;
+ arch.ANOP = ANOP;
+ arch.APCDATA = APCDATA;
+ arch.ARET = ARETURN;
+ arch.ASIGNAME = ASIGNAME;
+ arch.ATEXT = ATEXT;
+ arch.ATYPE = ATYPE;
+ arch.AUNDEF = AUNDEF;
+ arch.AVARDEF = AVARDEF;
+ arch.AVARKILL = AVARKILL;
+ arch.D_AUTO = D_AUTO;
+ arch.D_BRANCH = D_BRANCH;
+ arch.D_NONE = D_NONE;
+ arch.D_PARAM = D_PARAM;
+ arch.MAXWIDTH = MAXWIDTH;
+ arch.afunclit = afunclit;
+ arch.anyregalloc = anyregalloc;
+ arch.betypeinit = betypeinit;
+ arch.bgen = bgen;
+ arch.cgen = cgen;
+ arch.cgen_asop = cgen_asop;
+ arch.cgen_call = cgen_call;
+ 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;
+ arch.regopt = regopt;
+ arch.regtyp = regtyp;
+ arch.sameaddr = sameaddr;
+ arch.smallindir = smallindir;
+ arch.stackaddr = stackaddr;
+ arch.unpatch = unpatch;
+
+ gcmain(argc, argv);
+}
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
-EXTERN Node* newproc;
-EXTERN Node* deferproc;
-EXTERN Node* deferreturn;
-EXTERN Node* panicindex;
-EXTERN Node* panicslice;
EXTERN Node* panicdiv;
-EXTERN Node* throwreturn;
extern vlong unmappedzero;
/*
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);
+
+void afunclit(Addr*, Node*);
+int anyregalloc(void);
+void betypeinit(void);
+void bgen(Node*, int, int, Prog*);
+void cgen(Node*, Node*);
+void cgen_asop(Node*);
+void cgen_call(Node*, int);
+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 *nam);
+void ggloblsym(Sym *s, int32 width, int8 flags);
+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*);
+void regopt(Prog*);
+int regtyp(Addr*);
+int sameaddr(Addr*, Addr*);
+int smallindir(Addr*, Addr*);
+int stackaddr(Addr*);
+Prog* unpatch(Prog*);
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "../gc/popt.h"
#define Z N
#define Adr Addr
/*
* prog.c
*/
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
- uint32 flags; // the bits below
- uint64 reguse; // registers implicitly used by this instruction
- uint64 regset; // registers implicitly set by this instruction
- uint64 regindex; // registers used by addressing mode
-};
-
-enum
-{
- // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
- Pseudo = 1<<1,
-
- // There's nothing to say about the instruction,
- // but it's still okay to see.
- OK = 1<<2,
-
- // Size of right-side write, or right-side read if no write.
- SizeB = 1<<3,
- SizeW = 1<<4,
- SizeL = 1<<5,
- SizeQ = 1<<6,
- SizeF = 1<<7, // float aka float32
- SizeD = 1<<8, // double aka float64
-
- // Left side (Prog.from): address taken, read, write.
- LeftAddr = 1<<9,
- LeftRead = 1<<10,
- LeftWrite = 1<<11,
-
- // Register in middle (Prog.reg); only ever read.
- RegRead = 1<<12,
- CanRegRead = 1<<13,
-
- // Right side (Prog.to): address taken, read, write.
- RightAddr = 1<<14,
- RightRead = 1<<15,
- RightWrite = 1<<16,
-
- // Instruction updates whichever of from/to is type D_OREG
- PostInc = 1<<17,
-
- // Instruction kinds
- Move = 1<<18, // straight move
- Conv = 1<<19, // size conversion
- Cjmp = 1<<20, // conditional jump
- Break = 1<<21, // breaks control flow (no fallthrough)
- Call = 1<<22, // function call
- Jump = 1<<23, // jump
- Skip = 1<<24, // data instruction
-};
-
void proginfo(ProgInfo*, Prog*);
// Many Power ISA arithmetic and logical instructions come in four
"anames9.c",
}},
{"cmd/gc", []string{
- "-cplx.c",
- "-pgen.c",
- "-plive.c",
- "-popt.c",
- "-y1.tab.c", // makefile dreg
"opnames.h",
}},
{"cmd/5g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/6g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/8g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/9g", []string{
- "../gc/cplx.c",
- "../gc/pgen.c",
- "../gc/plive.c",
- "../gc/popt.c",
- "../gc/popt.h",
"$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
}},
{"cmd/5l", []string{
fatal("offmod: not TFIELD: %lT", f);
f->width = o;
o += widthptr;
- if(o >= MAXWIDTH) {
+ if(o >= arch.MAXWIDTH) {
yyerror("interface too large");
o = widthptr;
}
if(w == 0)
lastzero = o;
o += w;
- if(o >= MAXWIDTH) {
+ if(o >= arch.MAXWIDTH) {
yyerror("type %lT too large", errtype);
o = 8; // small but nonzero
}
dowidth(t->type);
if(t->type->width != 0) {
- cap = (MAXWIDTH-1) / t->type->width;
+ cap = (arch.MAXWIDTH-1) / t->type->width;
if(t->bound > cap)
yyerror("type %lT larger than address space", t);
}
simtype[TFUNC] = tptr;
simtype[TUNSAFEPTR] = tptr;
- /* pick up the backend typedefs */
- for(i=0; typedefs[i].name; i++) {
- s = lookup(typedefs[i].name);
- s1 = pkglookup(typedefs[i].name, builtinpkg);
+ /* pick up the backend arch.typedefs */
+ for(i=0; arch.typedefs[i].name; i++) {
+ s = lookup(arch.typedefs[i].name);
+ s1 = pkglookup(arch.typedefs[i].name, builtinpkg);
- etype = typedefs[i].etype;
+ etype = arch.typedefs[i].etype;
if(etype < 0 || etype >= nelem(types))
fatal("typeinit: %s bad etype", s->name);
- sameas = typedefs[i].sameas;
+ sameas = arch.typedefs[i].sameas;
if(sameas < 0 || sameas >= nelem(types))
fatal("typeinit: %s bad sameas", s->name);
simtype[etype] = sameas;
#include <u.h>
#include <libc.h>
-#include "gg.h"
+#include "go.h"
static void subnode(Node *nr, Node *ni, Node *nc);
static void minus(Node *nl, Node *res);
subnode(&n1, &n2, f);
subnode(&n3, &n4, t);
- cgen(&n1, &n3);
- cgen(&n2, &n4);
+ arch.cgen(&n1, &n3);
+ arch.cgen(&n2, &n4);
break;
}
}
if(res->addable) {
subnode(&n1, &n2, res);
tempname(&tmp, n1.type);
- cgen(n->left, &tmp);
- cgen(n->right, &n2);
- cgen(&tmp, &n1);
+ arch.cgen(n->left, &tmp);
+ arch.cgen(n->right, &n2);
+ arch.cgen(&tmp, &n1);
return;
}
break;
}
subnode(&n1, &n2, nl);
if(n->op == OREAL) {
- cgen(&n1, res);
+ arch.cgen(&n1, res);
return;
}
- cgen(&n2, res);
+ arch.cgen(&n2, res);
return;
}
}
if(!res->addable) {
- igen(res, &n1, N);
- cgen(n, &n1);
- regfree(&n1);
+ arch.igen(res, &n1, N);
+ arch.cgen(n, &n1);
+ arch.regfree(&n1);
return;
}
if(n->addable) {
case OCALLFUNC:
case OCALLMETH:
case OCALLINTER:
- igen(n, &n1, res);
+ arch.igen(n, &n1, res);
complexmove(&n1, res);
- regfree(&n1);
+ arch.regfree(&n1);
return;
case OCONV:
if(nr != N) {
if(nl->ullman > nr->ullman && !nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(!nr->addable) {
tempname(&tnr, nr->type);
- cgen(nr, &tnr);
+ arch.cgen(nr, &tnr);
nr = &tnr;
}
}
if(!nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(nr != N) {
if(nl->ullman > nr->ullman && !nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(!nr->addable) {
tempname(&tnr, nr->type);
- cgen(nr, &tnr);
+ arch.cgen(nr, &tnr);
nr = &tnr;
}
}
if(!nl->addable) {
tempname(&tnl, nl->type);
- cgen(nl, &tnl);
+ arch.cgen(nl, &tnl);
nl = &tnl;
}
if(op == ONE)
true = !true;
- bgen(&na, true, likely, to);
+ arch.bgen(&na, true, likely, to);
}
void
ra.op = OMINUS;
ra.left = nl;
ra.type = nl->type;
- cgen(&ra, res);
+ arch.cgen(&ra, res);
}
// build and execute tree
ra.left = &n1;
ra.right = &n3;
ra.type = n1.type;
- cgen(&ra, &n5);
+ arch.cgen(&ra, &n5);
memset(&ra, 0, sizeof(ra));
ra.op = op;
ra.left = &n2;
ra.right = &n4;
ra.type = n2.type;
- cgen(&ra, &n6);
+ arch.cgen(&ra, &n6);
}
// build and execute tree
ra.left = &rm1;
ra.right = &rm2;
ra.type = rm1.type;
- cgen(&ra, &tmp);
+ arch.cgen(&ra, &tmp);
// imag part
memset(&rm1, 0, sizeof(rm1));
ra.left = &rm1;
ra.right = &rm2;
ra.type = rm1.type;
- cgen(&ra, &n6);
+ arch.cgen(&ra, &n6);
// tmp ->real part
- cgen(&tmp, &n5);
+ arch.cgen(&tmp, &n5);
}
b = Bopen(asmhdr, OWRITE);
if(b == nil)
fatal("open %s: %r", asmhdr);
- Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name);
+ Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", arch.thechar, localpkg->name);
for(l=asmlist; l; l=l->next) {
n = l->n;
if(isblanksym(n->sym))
//dump("gen", n);
lno = setlineno(n);
- wasregalloc = anyregalloc();
+ wasregalloc = arch.anyregalloc();
if(n == N)
goto ret;
// if there are pending gotos, resolve them all to the current pc.
for(p1=lab->gotopc; p1; p1=p2) {
- p2 = unpatch(p1);
- patch(p1, pc);
+ p2 = arch.unpatch(p1);
+ arch.patch(p1, pc);
}
lab->gotopc = P;
if(lab->labelpc == P)
// of the label in the OLABEL case above.)
lab = newlab(n);
if(lab->labelpc != P)
- gjmp(lab->labelpc);
+ arch.gjmp(lab->labelpc);
else
- lab->gotopc = gjmp(lab->gotopc);
+ lab->gotopc = arch.gjmp(lab->gotopc);
break;
case OBREAK:
yyerror("invalid break label %S", n->left->sym);
break;
}
- gjmp(lab->breakpc);
+ arch.gjmp(lab->breakpc);
break;
}
if(breakpc == P) {
yyerror("break is not in a loop");
break;
}
- gjmp(breakpc);
+ arch.gjmp(breakpc);
break;
case OCONTINUE:
yyerror("invalid continue label %S", n->left->sym);
break;
}
- gjmp(lab->continpc);
+ arch.gjmp(lab->continpc);
break;
}
if(continpc == P) {
yyerror("continue is not in a loop");
break;
}
- gjmp(continpc);
+ arch.gjmp(continpc);
break;
case OFOR:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
scontin = continpc;
continpc = pc;
lab->continpc = continpc;
}
gen(n->nincr); // contin: incr
- patch(p1, pc); // test:
- bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
+ arch.patch(p1, pc); // test:
+ arch.bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
genlist(n->nbody); // body
- gjmp(continpc);
- patch(breakpc, pc); // done:
+ arch.gjmp(continpc);
+ arch.patch(breakpc, pc); // done:
continpc = scontin;
breakpc = sbreak;
if(lab) {
break;
case OIF:
- p1 = gjmp(P); // goto test
- p2 = gjmp(P); // p2: goto else
- patch(p1, pc); // test:
- bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
+ p1 = arch.gjmp(P); // goto test
+ p2 = arch.gjmp(P); // p2: goto else
+ arch.patch(p1, pc); // test:
+ arch.bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
genlist(n->nbody); // then
- p3 = gjmp(P); // goto done
- patch(p2, pc); // else:
+ p3 = arch.gjmp(P); // goto done
+ arch.patch(p2, pc); // else:
genlist(n->nelse); // else
- patch(p3, pc); // done:
+ arch.patch(p3, pc); // done:
break;
case OSWITCH:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- patch(p1, pc); // test:
+ arch.patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
- patch(breakpc, pc); // done:
+ arch.patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
case OSELECT:
sbreak = breakpc;
- p1 = gjmp(P); // goto test
- breakpc = gjmp(P); // break: goto done
+ p1 = arch.gjmp(P); // goto test
+ breakpc = arch.gjmp(P); // break: goto done
// define break label
if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- patch(p1, pc); // test:
+ arch.patch(p1, pc); // test:
genlist(n->nbody); // select() body
- patch(breakpc, pc); // done:
+ arch.patch(breakpc, pc); // done:
breakpc = sbreak;
if(lab != L)
lab->breakpc = P;
break;
case OASOP:
- cgen_asop(n);
+ arch.cgen_asop(n);
break;
case ODCL:
break;
case OCALLINTER:
- cgen_callinter(n, N, 0);
+ arch.cgen_callinter(n, N, 0);
break;
case OCALLFUNC:
- cgen_call(n, 0);
+ arch.cgen_call(n, 0);
break;
case OPROC:
case ORETURN:
case ORETJMP:
- cgen_ret(n);
+ arch.cgen_ret(n);
break;
case OCHECKNIL:
}
ret:
- if(anyregalloc() != wasregalloc) {
+ if(arch.anyregalloc() != wasregalloc) {
dump("node", n);
fatal("registers left allocated");
}
if(n2.left->op == ONAME)
n2.left->class = PFUNC;
- cgen_call(&n2, proc);
+ arch.cgen_call(&n2, proc);
}
/*
break;
case OCALLINTER:
- cgen_callinter(n->left, N, proc);
+ arch.cgen_callinter(n->left, N, proc);
break;
case OCALLFUNC:
- cgen_call(n->left, proc);
+ arch.cgen_call(n->left, proc);
break;
}
switch(nr->op) {
case ONAME:
if(!(nr->class & PHEAP) && nr->class != PEXTERN && nr->class != PFUNC && nr->class != PPARAMREF)
- gused(nr);
+ arch.gused(nr);
break;
// unary
default:
tempname(&tmp, nr->type);
cgen_as(&tmp, nr);
- gused(&tmp);
+ arch.gused(&tmp);
}
}
}
ullmancalc(&z);
- cgen(&z, n);
+ arch.cgen(&z, n);
}
/*
tl = nl->type;
if(tl == T)
return;
- if(isfat(tl)) {
+ if(arch.isfat(tl)) {
if(nl->op == ONAME)
gvardef(nl);
- clearfat(nl);
+ arch.clearfat(nl);
return;
}
clearslim(nl);
if(tl == T)
return;
- cgen(nr, nl);
+ arch.cgen(nr, nl);
}
/*
Node *tmp;
tmp = temp(types[tptr]);
- cgen(n->right, tmp);
+ arch.cgen(n->right, tmp);
gvardef(res);
dst = *res;
dst.type = types[tptr];
dst.xoffset += widthptr;
- cgen(tmp, &dst);
+ arch.cgen(tmp, &dst);
dst.xoffset -= widthptr;
- cgen(n->left, &dst);
+ arch.cgen(n->left, &dst);
}
/*
if(isnil(n->left)) {
tempname(&src, n->left->type);
- cgen(n->left, &src);
+ arch.cgen(n->left, &src);
} else
src = *n->left;
if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR)
if(n->op == OSLICEARR || n->op == OSLICE3ARR) {
if(!isptr[n->left->type->etype])
fatal("slicearr is supposed to work on pointer: %+N\n", n);
- cgen(&src, base);
+ arch.cgen(&src, base);
cgen_checknil(base);
} else {
src.type = types[tptr];
- cgen(&src, base);
+ arch.cgen(&src, base);
}
// committed to the update
// compute len and cap.
// len = n-i, cap = m-i, and offs = i*width.
// computing offs last lets the multiply overwrite i.
- cgen(len, tmplen);
+ arch.cgen(len, tmplen);
if(n->op != OSLICESTR)
- cgen(cap, tmpcap);
+ arch.cgen(cap, tmpcap);
// if new cap != 0 { base += add }
// This avoids advancing base past the end of the underlying array/string,
// 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 = gjmp(P);
- p2 = gjmp(P);
- patch(p1, pc);
+ p1 = arch.gjmp(P);
+ p2 = arch.gjmp(P);
+ arch.patch(p1, pc);
nodconst(&con, tmpcap->type, 0);
cmp = nod(OEQ, tmpcap, &con);
typecheck(&cmp, Erv);
- bgen(cmp, 1, -1, p2);
+ arch.bgen(cmp, 1, -1, p2);
add = nod(OADD, base, offs);
typecheck(&add, Erv);
- cgen(add, base);
+ arch.cgen(add, base);
- patch(p2, pc);
+ arch.patch(p2, pc);
}
// dst.array = src.array [ + lo *width ]
dst = *res;
dst.xoffset += Array_array;
dst.type = types[tptr];
- cgen(base, &dst);
+ arch.cgen(base, &dst);
// dst.len = hi [ - lo ]
dst = *res;
dst.xoffset += Array_nel;
dst.type = types[simtype[TUINT]];
- cgen(tmplen, &dst);
+ arch.cgen(tmplen, &dst);
if(n->op != OSLICESTR) {
// dst.cap = cap [ - lo ]
dst = *res;
dst.xoffset += Array_cap;
dst.type = types[simtype[TUINT]];
- cgen(tmpcap, &dst);
+ arch.cgen(tmpcap, &dst);
}
}
MaxStackVarSize = 10*1024*1024,
};
-extern vlong MAXWIDTH;
-
/*
* note this is the representation
* of the compilers string literals,
int sameas;
};
-extern Typedef typedefs[];
-
typedef struct Sig Sig;
struct Sig
{
EXTERN Node* typesw;
EXTERN Node* nblank;
-extern int thechar;
-extern char* thestring;
-extern LinkArch* thelinkarch;
EXTERN int use_sse;
EXTERN char* hunk;
int duint64(Sym *s, int off, uint64 v);
int duint8(Sym *s, int off, uint8 v);
int duintptr(Sym *s, int off, uint64 v);
-int dsname(Sym *s, int off, char *dat, int ndat);
void dumpobj(void);
Sym* stringsym(char*, int);
void slicebytes(Node*, char*, int);
EXTERN int disable_checknil;
EXTERN vlong zerosize;
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node *n, int true, int likely, Prog *to);
void checknil(Node*, NodeList**);
-void expandchecks(Prog*);
-void cgen(Node*, Node*);
-void cgen_asop(Node *n);
-void cgen_call(Node *n, int proc);
-void cgen_callinter(Node *n, Node *res, int proc);
void cgen_checknil(Node*);
-void cgen_ret(Node *n);
-void clearfat(Node *n);
void compile(Node*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int off, char *str);
-int dgostrlitptr(Sym*, int off, Strlit*);
-int dstringptr(Sym *s, int off, char *str);
-int dsymptr(Sym *s, int off, Sym *x, int xoff);
int duintxx(Sym *s, int off, uint64 v, int wid);
-void dumpdata(void);
-void fixautoused(Prog*);
-void gdata(Node*, Node*, int);
-void gdatacomplex(Node*, Mpcplx*);
-void gdatastring(Node*, Strlit*);
-void ggloblnod(Node *nam);
-void ggloblsym(Sym *s, int32 width, int8 flags);
void gvardef(Node*);
void gvarkill(Node*);
-Prog* gjmp(Prog*);
-void gused(Node*);
void movelarge(NodeList*);
-int isfat(Type*);
-void linkarchinit(void);
void liveness(Node*, Prog*, Sym*, Sym*);
void twobitwalktype1(Type*, vlong*, Bvec*);
-void markautoused(Prog*);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
void nopout(Prog*);
-void patch(Prog*, Prog*);
-Prog* unpatch(Prog*);
#pragma varargck type "B" Mpint*
#pragma varargck type "E" int
* racewalk.c
*/
void racewalk(Node *fn);
+
+/*
+ * flow.c
+ */
+typedef struct Flow Flow;
+typedef struct Graph Graph;
+
+struct Flow {
+ Prog* prog; // actual instruction
+ Flow* p1; // predecessors of this instruction: p1,
+ Flow* p2; // and then p2 linked though p2link.
+ Flow* p2link;
+ Flow* s1; // successors of this instruction (at most two: s1 and s2).
+ Flow* s2;
+ Flow* link; // next instruction in function code
+
+ int32 active; // usable by client
+
+ int32 rpo; // reverse post ordering
+ uint16 loop; // x5 for every loop
+ uchar refset; // diagnostic generated
+};
+
+struct Graph
+{
+ Flow* start;
+ int num;
+
+ // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
+ // and each non-dead Flow node f has g->rpo[f->rpo] == f.
+ Flow** rpo;
+};
+
+void fixjmp(Prog*);
+Graph* flowstart(Prog*, int);
+void flowrpo(Graph*);
+void flowend(Graph*);
+void mergetemp(Prog*);
+void nilopt(Prog*);
+int noreturn(Prog*);
+Flow* uniqp(Flow*);
+Flow* uniqs(Flow*);
+
+/*
+ * interface to back end
+ */
+
+typedef struct ProgInfo ProgInfo;
+struct ProgInfo
+{
+ uint32 flags; // the bits below
+ uint64 reguse; // registers implicitly used by this instruction
+ uint64 regset; // registers implicitly set by this instruction
+ uint64 regindex; // registers used by addressing mode
+};
+
+enum
+{
+ // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
+ Pseudo = 1<<1,
+
+ // There's nothing to say about the instruction,
+ // but it's still okay to see.
+ OK = 1<<2,
+
+ // Size of right-side write, or right-side read if no write.
+ SizeB = 1<<3,
+ SizeW = 1<<4,
+ SizeL = 1<<5,
+ SizeQ = 1<<6,
+ SizeF = 1<<7, // float aka float32
+ SizeD = 1<<8, // double aka float64
+
+ // Left side (Prog.from): address taken, read, write.
+ LeftAddr = 1<<9,
+ LeftRead = 1<<10,
+ LeftWrite = 1<<11,
+
+ // Register in middle (Prog.reg); only ever read. (arm, ppc64)
+ RegRead = 1<<12,
+ CanRegRead = 1<<13,
+
+ // Right side (Prog.to): address taken, read, write.
+ RightAddr = 1<<14,
+ RightRead = 1<<15,
+ RightWrite = 1<<16,
+
+ // Instruction kinds
+ Move = 1<<17, // straight move
+ Conv = 1<<18, // size conversion
+ Cjmp = 1<<19, // conditional jump
+ Break = 1<<20, // breaks control flow (no fallthrough)
+ Call = 1<<21, // function call
+ Jump = 1<<22, // jump
+ Skip = 1<<23, // data instruction
+
+ // Set, use, or kill of carry bit.
+ // Kill means we never look at the carry bit after this kind of instruction.
+ SetCarry = 1<<24,
+ UseCarry = 1<<25,
+ KillCarry = 1<<26,
+
+ // Special cases for register use. (amd64, 386)
+ ShiftCX = 1<<27, // possible shift by CX
+ ImulAXDX = 1<<28, // possible multiply into DX:AX
+
+ // Instruction updates whichever of from/to is type D_OREG. (ppc64)
+ PostInc = 1<<29,
+};
+
+typedef struct Arch Arch;
+
+struct Arch
+{
+ int thechar;
+ char *thestring;
+ LinkArch *thelinkarch;
+ Typedef *typedefs;
+ Prog zprog;
+
+ int ACALL;
+ int ACHECKNIL;
+ int ADATA;
+ int AFUNCDATA;
+ int AGLOBL;
+ int AJMP;
+ int ANAME;
+ int ANOP;
+ int APCDATA;
+ int ARET;
+ int ASIGNAME;
+ int ATEXT;
+ int ATYPE;
+ int AUNDEF;
+ int AVARDEF;
+ int AVARKILL;
+ int D_AUTO;
+ int D_BRANCH;
+ int D_NONE;
+ int D_PARAM;
+ vlong MAXWIDTH;
+
+ void (*afunclit)(Addr*, Node*);
+ int (*anyregalloc)(void);
+ void (*betypeinit)(void);
+ void (*bgen)(Node*, int, int, Prog*);
+ void (*cgen)(Node*, Node*);
+ void (*cgen_asop)(Node*);
+ void (*cgen_call)(Node*, int);
+ 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*);
+ void (*regopt)(Prog*);
+ int (*regtyp)(Addr*);
+ int (*sameaddr)(Addr*, Addr*);
+ int (*smallindir)(Addr*, Addr*);
+ int (*stackaddr)(Addr*);
+ Prog* (*unpatch)(Prog*);
+};
+
+EXTERN Arch arch;
+
+EXTERN Node *newproc;
+EXTERN Node *deferproc;
+EXTERN Node *deferreturn;
+EXTERN Node *panicindex;
+EXTERN Node *panicslice;
+EXTERN Node *throwreturn;
+
+int gcmain(int, char**);
void
usage(void)
{
- print("usage: %cg [options] file.go...\n", thechar);
+ print("usage: %cg [options] file.go...\n", arch.thechar);
flagprint(1);
exits("usage");
}
p = expstring();
if(strcmp(p, "X:none") == 0)
p = "";
- print("%cg version %s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
+ print("%cg version %s%s%s\n", arch.thechar, getgoversion(), *p ? " " : "", p);
exits(0);
}
int
-main(int argc, char *argv[])
+gcmain(int argc, char *argv[])
{
int i;
NodeList *l;
char *p;
-
+
#ifdef SIGBUS
signal(SIGBUS, fault);
signal(SIGSEGV, fault);
// Tell the FPU to handle all exceptions.
setfcr(FPPDBL|FPRNR);
#endif
- // Allow GOARCH=thestring or GOARCH=thestringsuffix,
+ // Allow GOARCH=arch.thestring or GOARCH=arch.thestringsuffix,
// but not other values.
p = getgoarch();
- if(strncmp(p, thestring, strlen(thestring)) != 0)
- sysfatal("cannot use %cg with GOARCH=%s", thechar, p);
+ if(strncmp(p, arch.thestring, strlen(arch.thestring)) != 0)
+ sysfatal("cannot use %cg with GOARCH=%s", arch.thechar, p);
goarch = p;
- linkarchinit();
- ctxt = linknew(thelinkarch);
+ arch.linkarchinit();
+ ctxt = linknew(arch.thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
Binit(&bstdout, 1, OWRITE);
flagcount("wb", "enable write barrier", &use_writebarrier);
flagcount("x", "debug lexer", &debug['x']);
flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']);
- if(thechar == '6')
+ if(arch.thechar == '6')
flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
flagparse(&argc, &argv, usage);
if(debug['l'] <= 1)
debug['l'] = 1 - debug['l'];
- if(thechar == '8') {
+ if(arch.thechar == '8') {
p = getgo386();
if(strcmp(p, "387") == 0)
use_sse = 0;
}
fmtinstallgo();
- betypeinit();
+ arch.betypeinit();
if(widthptr == 0)
fatal("betypeinit failed");
snprint(namebuf, sizeof(namebuf), "%Z.a", name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%Z.%c", name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
return 0;
snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.a", goroot, goos, goarch, suffixsep, suffix, name);
if(access(namebuf, 0) >= 0)
return 1;
- snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.%c", goroot, goos, goarch, suffixsep, suffix, name, thechar);
+ snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.%c", goroot, goos, goarch, suffixsep, suffix, name, arch.thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
}
// backend-specific builtin types (e.g. int).
- for(i=0; typedefs[i].name; i++) {
- s = lookup(typedefs[i].name);
+ for(i=0; arch.typedefs[i].name; i++) {
+ s = lookup(arch.typedefs[i].name);
if(s->def == N) {
- s->def = typenod(types[typedefs[i].etype]);
+ s->def = typenod(types[arch.typedefs[i].etype]);
s->origpkg = builtinpkg;
}
}
p = strrchr(namebuf, '.');
if(p != nil)
*p = 0;
- outfile = smprint("%s.%c", namebuf, thechar);
+ outfile = smprint("%s.%c", namebuf, arch.thechar);
}
}
externdcl = tmp;
zero = pkglookup("zerovalue", runtimepkg);
- ggloblsym(zero, zerosize, DUPOK|RODATA);
+ arch.ggloblsym(zero, zerosize, DUPOK|RODATA);
- dumpdata();
+ arch.dumpdata();
writeobj(ctxt, bout);
if(writearchive) {
if(size&1)
Bputc(bout, 0);
Bseek(bout, startobj - ArhdrSize, 0);
- snprint(namebuf, sizeof namebuf, "_go_.%c", thechar);
+ snprint(namebuf, sizeof namebuf, "_go_.%c", arch.thechar);
formathdr(arhdr, namebuf, size);
Bwrite(bout, arhdr, ArhdrSize);
}
continue;
dowidth(n->type);
- ggloblnod(n);
+ arch.ggloblnod(n);
}
for(l=funcsyms; l; l=l->next) {
n = l->n;
- dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
- ggloblsym(n->sym, widthptr, DUPOK|RODATA);
+ arch.dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
+ arch.ggloblsym(n->sym, widthptr, DUPOK|RODATA);
}
// Do not reprocess funcsyms on next dumpglobls call.
off = 0;
// string header
- off = dsymptr(sym, off, sym, widthptr+widthint);
+ off = arch.dsymptr(sym, off, sym, widthptr+widthint);
off = duintxx(sym, off, len, widthint);
// string data
m = 8;
if(m > len-n)
m = len-n;
- off = dsname(sym, off, s+n, m);
+ off = arch.dsname(sym, off, s+n, m);
}
off = duint8(sym, off, 0); // terminating NUL for runtime
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
- ggloblsym(sym, off, DUPOK|RODATA);
+ arch.ggloblsym(sym, off, DUPOK|RODATA);
return sym;
}
m = 8;
if(m > len-n)
m = len-n;
- off = dsname(sym, off, s+n, m);
+ off = arch.dsname(sym, off, s+n, m);
}
- ggloblsym(sym, off, NOPTR);
+ arch.ggloblsym(sym, off, NOPTR);
if(nam->op != ONAME)
fatal("slicebytes %N", nam);
off = nam->xoffset;
- off = dsymptr(nam->sym, off, sym, 0);
+ off = arch.dsymptr(nam->sym, off, sym, 0);
off = duintxx(nam->sym, off, len, widthint);
duintxx(nam->sym, off, len, widthint);
}
#include <u.h>
#include <libc.h>
#include "md5.h"
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
+//#include "opt.h"
#include "../../runtime/funcdata.h"
+#include "../ld/textflag.h"
static void allocauto(Prog* p);
static void emitptrargsmap(void);
pnod = newname(sym);
pnod->class = PEXTERN;
nodconst(&nod, types[TINT32], funcdatakind);
- gins(AFUNCDATA, &nod, pnod);
+ arch.gins(arch.AFUNCDATA, &nod, pnod);
return sym;
}
// 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 isfat(n->type).
+// or 'fat' variables, those satisfying arch.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()
case PAUTO:
case PPARAM:
case PPARAMOUT:
- gins(as, N, n);
+ arch.gins(as, N, n);
}
}
void
gvardef(Node *n)
{
- gvardefx(n, AVARDEF);
+ gvardefx(n, arch.AVARDEF);
}
void
gvarkill(Node *n)
{
- gvardefx(n, AVARKILL);
+ gvardefx(n, arch.AVARKILL);
}
static void
Prog *p;
for(p = firstp; p != P; p = p->link) {
- while(p->link != P && (p->link->as == AVARDEF || p->link->as == AVARKILL))
+ while(p->link != P && (p->link->as == arch.AVARDEF || p->link->as == arch.AVARKILL))
p->link = p->link->link;
- if(p->to.type == D_BRANCH)
- while(p->to.u.branch != P && (p->to.u.branch->as == AVARDEF || p->to.u.branch->as == AVARKILL))
+ if(p->to.type == arch.D_BRANCH)
+ while(p->to.u.branch != P && (p->to.u.branch->as == arch.AVARDEF || p->to.u.branch->as == arch.AVARKILL))
p->to.u.branch = p->to.u.branch->link;
}
}
continpc = P;
breakpc = P;
- pl = newplist();
+ pl = arch.newplist();
pl->name = linksym(curfn->nname->sym);
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
+ ptxt = arch.gins(arch.ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
if(fn->dupok)
- ptxt->TEXTFLAG |= DUPOK;
+ arch.thelinkarch->settextflag(ptxt, arch.thelinkarch->textflag(ptxt) | DUPOK);
if(fn->wrapper)
- ptxt->TEXTFLAG |= WRAPPER;
+ arch.thelinkarch->settextflag(ptxt, arch.thelinkarch->textflag(ptxt) | WRAPPER);
if(fn->needctxt)
- ptxt->TEXTFLAG |= NEEDCTXT;
+ arch.thelinkarch->settextflag(ptxt, arch.thelinkarch->textflag(ptxt) | NEEDCTXT);
if(fn->nosplit)
- ptxt->TEXTFLAG |= NOSPLIT;
+ arch.thelinkarch->settextflag(ptxt, arch.thelinkarch->textflag(ptxt) | NOSPLIT);
// Clumsy but important.
// See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered.
if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) {
if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0)
- ptxt->TEXTFLAG |= WRAPPER;
+ arch.thelinkarch->settextflag(ptxt, arch.thelinkarch->textflag(ptxt) | WRAPPER);
}
- afunclit(&ptxt->from, curfn->nname);
+ arch.afunclit(&ptxt->from, curfn->nname);
- ginit();
+ arch.ginit();
gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
for(t=curfn->paramfld; t; t=t->down)
- gtrack(tracksym(t->type));
+ arch.gtrack(tracksym(t->type));
for(l=fn->dcl; l; l=l->next) {
n = l->n;
case PPARAM:
case PPARAMOUT:
nodconst(&nod1, types[TUINTPTR], l->n->type->width);
- p = gins(ATYPE, l->n, &nod1);
+ p = arch.gins(arch.ATYPE, l->n, &nod1);
p->from.gotype = linksym(ngotype(l->n));
break;
}
genlist(curfn->enter);
genlist(curfn->nbody);
- gclean();
+ arch.gclean();
checklabels();
if(nerrors != 0)
goto ret;
lineno = curfn->endlineno;
if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
+ arch.ginscall(throwreturn, 0);
- ginit();
+ arch.ginit();
// TODO: Determine when the final cgen_ret can be omitted. Perhaps always?
- cgen_ret(nil);
+ arch.cgen_ret(nil);
if(hasdefer) {
// deferreturn pretends to have one uintptr argument.
// Reserve space for it so stack scanner is happy.
if(maxarg < widthptr)
maxarg = widthptr;
}
- gclean();
+ arch.gclean();
if(nerrors != 0)
goto ret;
- pc->as = ARET; // overwrite AEND
+ pc->as = arch.ARET; // overwrite AEND
pc->lineno = lineno;
fixjmp(ptxt);
if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
+ arch.regopt(ptxt);
nilopt(ptxt);
}
- expandchecks(ptxt);
+ arch.expandchecks(ptxt);
oldstksize = stksize;
allocauto(ptxt);
gcsymdup(gcargs);
gcsymdup(gclocals);
- defframe(ptxt);
+ arch.defframe(ptxt);
if(0)
frame(0);
for(j = 0; j < bv->n; j += 32)
off = duint32(sym, off, bv->b[j/32]);
}
- ggloblsym(sym, off, RODATA);
+ arch.ggloblsym(sym, off, RODATA);
free(bv);
}
if (ll->n->class == PAUTO)
ll->n->used = 0;
- markautoused(ptxt);
+ arch.markautoused(ptxt);
listsort(&curfn->dcl, cmpstackvar);
if (n->class == PAUTO && n->op == ONAME && !n->used) {
// No locals used at all
curfn->dcl = nil;
- fixautoused(ptxt);
+ arch.fixautoused(ptxt);
return;
}
dowidth(n->type);
w = n->type->width;
- if(w >= MAXWIDTH || w < 0)
+ if(w >= arch.MAXWIDTH || w < 0)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, n->type->align);
if(haspointers(n->type))
stkptrsize = stksize;
- if(thechar == '5' || thechar == '9')
+ if(arch.thechar == '5' || arch.thechar == '9')
stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) {
setlineno(curfn);
stksize = rnd(stksize, widthreg);
stkptrsize = rnd(stkptrsize, widthreg);
- fixautoused(ptxt);
+ arch.fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl; ll != nil; ll=ll->next) {
dump("checknil", n);
fatal("bad checknil");
}
- if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
- regalloc(®, types[tptr], n);
- cgen(n, ®);
- gins(ACHECKNIL, ®, N);
- regfree(®);
+ if(((arch.thechar == '5' || arch.thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
+ arch.regalloc(®, types[tptr], n);
+ arch.cgen(n, ®);
+ arch.gins(arch.ACHECKNIL, ®, N);
+ arch.regfree(®);
return;
}
- gins(ACHECKNIL, n, N);
+ arch.gins(arch.ACHECKNIL, n, N);
}
#include <u.h>
#include <libc.h>
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
#include "../ld/textflag.h"
#include "../../runtime/funcdata.h"
#include "../../runtime/mgc0.h"
fatal("iscall: prog is nil");
if(name == nil)
fatal("iscall: function name is nil");
- if(prog->as != ACALL)
+ if(prog->as != arch.ACALL)
return 0;
return name == prog->to.sym;
}
bb = newblock(firstp);
arrayadd(cfg, &bb);
for(p = firstp; p != P; p = p->link) {
- if(p->to.type == D_BRANCH) {
+ if(p->to.type == arch.D_BRANCH) {
if(p->to.u.branch == nil)
fatal("prog branch to nil");
if(p->to.u.branch->opt == nil) {
p->to.u.branch->opt = newblock(p->to.u.branch);
arrayadd(cfg, &p->to.u.branch->opt);
}
- if(p->as != AJMP && p->link != nil && p->link->opt == nil) {
+ if(p->as != arch.AJMP && p->link != nil && p->link->opt == nil) {
p->link->opt = newblock(p->link);
arrayadd(cfg, &p->link->opt);
}
// Stop before an unreachable RET, to avoid creating
// unreachable control flow nodes.
- if(p->link != nil && p->link->as == ARET && p->link->mode == 1)
+ if(p->link != nil && p->link->as == arch.ARET && p->link->mode == 1)
break;
// Collect basic blocks with selectgo calls.
if(isselectgocall(p))
arrayadd(selectgo, &bb);
}
- if(bb->last->to.type == D_BRANCH)
+ if(bb->last->to.type == arch.D_BRANCH)
addedge(bb, bb->last->to.u.branch->opt);
if(bb->last->link != nil) {
// Add a fall-through when the instruction is
// not an unconditional control transfer.
- switch(bb->last->as) {
- case AJMP:
- case ARET:
- case AUNDEF:
- break;
- default:
+ if(bb->last->as != arch.AJMP && bb->last->as != arch.ARET && bb->last->as != arch.AUNDEF)
addedge(bb, bb->last->link->opt);
- }
}
}
bvresetall(varkill);
bvresetall(avarinit);
- proginfo(&info, prog);
- if(prog->as == ARET) {
+ arch.proginfo(&info, prog);
+ if(prog->as == arch.ARET) {
// Return instructions implicitly read all the arguments. For
// the sake of correctness, out arguments must be read. For the
// sake of backtrace quality, we read in arguments as well.
// If we added it to uevar too, we'd not see any kill
// and decide that the varible was live entry, which it is not.
// So only use uevar in the non-addrtaken case.
- // The p->to.type == D_NONE limits the bvset to
+ // The p->to.type == arch.D_NONE limits the bvset to
// non-tail-call return instructions; see note above
// the for loop for details.
- if(!node->addrtaken && prog->to.type == D_NONE)
+ if(!node->addrtaken && prog->to.type == arch.D_NONE)
bvset(uevar, i);
break;
}
}
return;
}
- if(prog->as == ATEXT) {
+ if(prog->as == arch.ATEXT) {
// A text instruction marks the entry point to a function and
// the definition point of all in arguments.
for(i = 0; i < arraylength(vars); i++) {
if(info.flags & (LeftRead | LeftAddr))
bvset(uevar, pos);
if(info.flags & LeftWrite)
- if(from->node != nil && !isfat(((Node*)(from->node))->type))
+ if(from->node != nil && !arch.isfat(((Node*)(from->node))->type))
bvset(varkill, pos);
}
}
if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node)
fatal("bad bookkeeping in liveness %N %d", to->node, pos);
if(((Node*)(to->node))->addrtaken) {
- if(prog->as != AVARKILL)
+ if(prog->as != arch.AVARKILL)
bvset(avarinit, pos);
- if(prog->as == AVARDEF || prog->as == AVARKILL)
+ if(prog->as == arch.AVARDEF || prog->as == arch.AVARKILL)
bvset(varkill, pos);
} else {
// RightRead is a read, obviously.
if((info.flags & RightRead) || (info.flags & (RightAddr|RightWrite)) == RightAddr)
bvset(uevar, pos);
if(info.flags & RightWrite)
- if(to->node != nil && (!isfat(((Node*)(to->node))->type) || prog->as == AVARDEF))
+ if(to->node != nil && (!arch.isfat(((Node*)(to->node))->type) || prog->as == arch.AVARDEF))
bvset(varkill, pos);
}
}
print("\tprog:\n");
for(prog = bb->first;; prog = prog->link) {
print("\t\t%P", prog);
- if(prog->as == APCDATA && prog->from.offset == PCDATA_StackMapIndex) {
+ if(prog->as == arch.APCDATA && prog->from.offset == PCDATA_StackMapIndex) {
pos = prog->to.offset;
live = *(Bvec**)arrayget(lv->livepointers, pos);
print(" ");
static void
checkprog(Node *fn, Prog *p)
{
- if(p->from.type == D_AUTO)
+ if(p->from.type == arch.D_AUTO)
checkauto(fn, p, p->from.node);
- if(p->from.type == D_PARAM)
+ if(p->from.type == arch.D_PARAM)
checkparam(fn, p, p->from.node);
- if(p->to.type == D_AUTO)
+ if(p->to.type == arch.D_AUTO)
checkauto(fn, p, p->to.node);
- if(p->to.type == D_PARAM)
+ if(p->to.type == arch.D_PARAM)
checkparam(fn, p, p->to.node);
}
for(p = firstp; p != P; p = p->link) {
if(0)
print("analyzing '%P'\n", p);
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case ATYPE:
- continue;
- }
- checkprog(fn, p);
+ if(p->as != arch.ADATA && p->as != arch.AGLOBL && p->as != arch.ANAME && p->as != arch.ASIGNAME && p->as != arch.ATYPE)
+ checkprog(fn, p);
}
}
Prog *p;
p = mal(sizeof(*p));
- clearp(p);
+ arch.clearp(p);
p->as = as;
return p;
}
nodconst(&from, types[TINT32], PCDATA_StackMapIndex);
nodconst(&to, types[TINT32], index);
- pcdata = unlinkedprog(APCDATA);
+ pcdata = unlinkedprog(arch.APCDATA);
pcdata->lineno = prog->lineno;
- naddr(&from, &pcdata->from, 0);
- naddr(&to, &pcdata->to, 0);
+ arch.naddr(&from, &pcdata->from, 0);
+ arch.naddr(&to, &pcdata->to, 0);
return pcdata;
}
static int
issafepoint(Prog *prog)
{
- return prog->as == ATEXT || prog->as == ACALL;
+ return prog->as == arch.ATEXT || prog->as == arch.ACALL;
}
// Initializes the sets for solving the live variables. Visits all the
// walk backward, emit pcdata and populate the maps
pos = bb->lastbitmapindex;
if(pos < 0) {
- // the first block we encounter should have the ATEXT so
+ // the first block we encounter should have the arch.ATEXT so
// at no point should pos ever be less than zero.
fatal("livenessepilogue");
}
// Useful sanity check: on entry to the function,
// the only things that can possibly be live are the
// input parameters.
- if(p->as == ATEXT) {
+ if(p->as == arch.ATEXT) {
for(j = 0; j < liveout->n; j++) {
if(!bvget(liveout, j))
continue;
// Ambiguously live variables are zeroed immediately after
// function entry. Mark them live for all the non-entry bitmaps
// so that GODEBUG=gcdead=1 mode does not poison them.
- if(p->as == ACALL)
+ if(p->as == arch.ACALL)
bvor(locals, locals, ambig);
// Show live pointer bitmaps.
if(msg != nil) {
fmtstrinit(&fmt);
fmtprint(&fmt, "%L: live at ", p->lineno);
- if(p->as == ACALL && p->to.node)
+ if(p->as == arch.ACALL && p->to.node)
fmtprint(&fmt, "call to %s:", ((Node*)(p->to.node))->sym->name);
- else if(p->as == ACALL)
+ else if(p->as == arch.ACALL)
fmtprint(&fmt, "indirect call:");
else
fmtprint(&fmt, "entry to %s:", ((Node*)(p->from.node))->sym->name);
// Only CALL instructions need a PCDATA annotation.
// The TEXT instruction annotation is implicit.
- if(p->as == ACALL) {
+ if(p->as == arch.ACALL) {
if(isdeferreturn(p)) {
// runtime.deferreturn modifies its return address to return
// back to the CALL, not to the subsequent instruction.
// Rewrite PCDATA instructions to use new numbering.
for(p=lv->ptxt; p != P; p=p->link) {
- if(p->as == APCDATA && p->from.offset == PCDATA_StackMapIndex) {
+ if(p->as == arch.APCDATA && p->from.offset == PCDATA_StackMapIndex) {
i = p->to.offset;
if(i >= 0)
p->to.offset = remap[i];
// program listing, with individual effects listed
for(p = bb->first;; p = p->link) {
print("%P\n", p);
- if(p->as == APCDATA && p->from.offset == PCDATA_StackMapIndex)
+ if(p->as == arch.APCDATA && p->from.offset == PCDATA_StackMapIndex)
pcdata = p->to.offset;
progeffects(p, lv->vars, uevar, varkill, avarinit);
printed = 0;
}
}
duint32(sym, 0, i); // number of bitmaps
- ggloblsym(sym, off, RODATA);
+ arch.ggloblsym(sym, off, RODATA);
}
static void
#include <u.h>
#include <libc.h>
-#include "gg.h"
-#include "opt.h"
+#include "go.h"
// p is a call instruction. Does the call fail to return?
int
int n;
n = 0;
- while(p != P && p->as == AJMP && p->to.type == D_BRANCH) {
+ while(p != P && p->as == arch.AJMP && p->to.type == arch.D_BRANCH) {
if(++n > 10) {
*jmploop = 1;
break;
if(p->opt != dead)
break;
p->opt = alive;
- if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch)
+ if(p->as != arch.ACALL && p->to.type == arch.D_BRANCH && p->to.u.branch)
mark(p->to.u.branch);
- if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
+ if(p->as == arch.AJMP || p->as == arch.ARET || p->as == arch.AUNDEF)
break;
}
}
for(p=firstp; p; p=p->link) {
if(debug['R'] && debug['v'])
print("%P\n", p);
- if(p->as != ACALL && p->to.type == D_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
+ if(p->as != arch.ACALL && p->to.type == arch.D_BRANCH && p->to.u.branch && p->to.u.branch->as == arch.AJMP) {
p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
if(debug['R'] && debug['v'])
print("->%P\n", p);
last = nil;
for(p=firstp; p; p=p->link) {
if(p->opt == dead) {
- if(p->link == P && p->as == ARET && last && last->as != ARET) {
- // This is the final ARET, and the code so far doesn't have one.
+ if(p->link == P && p->as == arch.ARET && last && last->as != arch.ARET) {
+ // This is the final arch.ARET, and the code so far doesn't have one.
// Let it stay. The register allocator assumes that all live code in
// the function can be traversed by starting at all the RET instructions
// and following predecessor links. If we remove the final RET,
if(!jmploop) {
last = nil;
for(p=firstp; p; p=p->link) {
- if(p->as == AJMP && p->to.type == D_BRANCH && p->to.u.branch == p->link) {
+ if(p->as == arch.AJMP && p->to.type == arch.D_BRANCH && p->to.u.branch == p->link) {
if(debug['R'] && debug['v'])
print("del %P\n", p);
continue;
nf = 0;
for(p = firstp; p != P; p = p->link) {
p->opt = nil; // should be already, but just in case
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(info.flags & Skip)
continue;
p->opt = (void*)1;
// Fill in pred/succ information.
for(f = start; f != nil; f = f->link) {
p = f->prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(!(info.flags & Break)) {
f1 = f->link;
f->s1 = f1;
f1->p1 = f;
}
- if(p->to.type == D_BRANCH) {
+ if(p->to.type == arch.D_BRANCH) {
if(p->to.u.branch == P)
fatal("pnil %P", p);
f1 = p->to.u.branch->opt;
return 0;
}
+enum {
+ LOOP = 3,
+};
+
static void
loopmark(Flow **rpo2r, int32 head, Flow *r)
{
// single-use (that's why we have so many!).
for(r = (TempFlow*)g->start; r != nil; r = (TempFlow*)r->f.link) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(p->from.node != N && ((Node*)(p->from.node))->opt && p->to.node != N && ((Node*)(p->to.node))->opt)
fatal("double node %P", p);
}
if(Debug > 1)
- dumpit("before", g->start, 0);
+ arch.dumpit("before", g->start, 0);
nkill = 0;
// Used in only one instruction, which had better be a write.
if((r = v->use) != nil && r->uselink == nil) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
if(p->to.node == v->node && (info.flags & RightWrite) && !(info.flags & RightRead)) {
- p->as = ANOP;
- p->to = zprog.to;
+ p->as = arch.ANOP;
+ p->to = arch.zprog.to;
v->removed = 1;
if(Debug)
print("drop write-only %S\n", v->node->sym);
// no jumps to the next instruction. Happens mainly in 386 compiler.
if((r = v->use) != nil && r->f.link == &r->uselink->f && r->uselink->uselink == nil && uniqp(r->f.link) == &r->f) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
p1 = r->f.link->prog;
- proginfo(&info1, p1);
+ arch.proginfo(&info1, p1);
enum {
SizeAny = SizeB | SizeW | SizeL | SizeQ | SizeF | SizeD,
};
!((info.flags|info1.flags) & (LeftAddr|RightAddr)) &&
(info.flags & SizeAny) == (info1.flags & SizeAny)) {
p1->from = p->from;
- excise(&r->f);
+ arch.excise(&r->f);
v->removed = 1;
if(Debug)
print("drop immediate-use %S\n", v->node->sym);
}
if(Debug > 1)
- dumpit("after", g->start, 0);
+ arch.dumpit("after", g->start, 0);
}
// Update node references to use merged temporaries.
v->end = p->pc;
if(v->start > p->pc)
v->start = p->pc;
- if(p->as == ARET || (p->as == AVARKILL && p->to.node == v->node))
+ if(p->as == arch.ARET || (p->as == arch.AVARKILL && p->to.node == v->node))
break;
}
return;
if(debug_checknil > 1 /* || strcmp(curfn->nname->sym->name, "f1") == 0 */)
- dumpit("nilopt", g->start, 0);
+ arch.dumpit("nilopt", g->start, 0);
ncheck = 0;
nkill = 0;
for(r = (NilFlow*)g->start; r != nil; r = (NilFlow*)r->f.link) {
p = r->f.prog;
- if(p->as != ACHECKNIL || !regtyp(&p->from))
+ if(p->as != arch.ACHECKNIL || !arch.regtyp(&p->from))
continue;
ncheck++;
- if(stackaddr(&p->from)) {
+ if(arch.stackaddr(&p->from)) {
if(debug_checknil && p->lineno > 1)
warnl(p->lineno, "removed nil check of SP address");
r->kill = 1;
for(r = (NilFlow*)g->start; r != nil; r = (NilFlow*)r->f.link) {
if(r->kill) {
nkill++;
- excise(&r->f);
+ arch.excise(&r->f);
}
}
for(r = rcheck; r != nil; r = (NilFlow*)uniqp(&r->f)) {
p = r->f.prog;
- proginfo(&info, p);
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
+ arch.proginfo(&info, p);
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from)) {
// Found initialization of value we're checking for nil.
// without first finding the check, so this one is unchecked.
return;
}
- if(r != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from)) {
+ if(r != rcheck && p->as == arch.ACHECKNIL && arch.sameaddr(&p->from, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
// If same check, stop this loop but still check
// alternate predecessors up to this point.
- if(r1 != rcheck && p->as == ACHECKNIL && sameaddr(&p->from, &rcheck->f.prog->from))
+ if(r1 != rcheck && p->as == arch.ACHECKNIL && arch.sameaddr(&p->from, &rcheck->f.prog->from))
break;
- proginfo(&info, p);
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from)) {
+ arch.proginfo(&info, p);
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from)) {
// Found initialization of value we're checking for nil.
// without first finding the check, so this one is unchecked.
rcheck->kill = 0;
if(r1->f.p1 == nil && r1->f.p2 == nil) {
print("lost pred for %P\n", rcheck->f.prog);
for(r1=r0; r1!=nil; r1=(NilFlow*)r1->f.p1) {
- proginfo(&info, r1->f.prog);
- print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from);
+ arch.proginfo(&info, r1->f.prog);
+ print("\t%P %d %d %D %D\n", r1->f.prog, info.flags&RightWrite, arch.sameaddr(&r1->f.prog->to, &rcheck->f.prog->from), &r1->f.prog->to, &rcheck->f.prog->from);
}
fatal("lost pred trail");
}
last = nil;
for(r = (NilFlow*)uniqs(&rcheck->f); r != nil; r = (NilFlow*)uniqs(&r->f)) {
p = r->f.prog;
- proginfo(&info, p);
+ arch.proginfo(&info, p);
- if((info.flags & LeftRead) && smallindir(&p->from, &rcheck->f.prog->from)) {
+ if((info.flags & LeftRead) && arch.smallindir(&p->from, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
- if((info.flags & (RightRead|RightWrite)) && smallindir(&p->to, &rcheck->f.prog->from)) {
+ if((info.flags & (RightRead|RightWrite)) && arch.smallindir(&p->to, &rcheck->f.prog->from)) {
rcheck->kill = 1;
return;
}
// Stop if another nil check happens.
- if(p->as == ACHECKNIL)
+ if(p->as == arch.ACHECKNIL)
return;
// Stop if value is lost.
- if((info.flags & RightWrite) && sameaddr(&p->to, &rcheck->f.prog->from))
+ if((info.flags & RightWrite) && arch.sameaddr(&p->to, &rcheck->f.prog->from))
return;
// Stop if memory write.
- if((info.flags & RightWrite) && !regtyp(&p->to))
+ if((info.flags & RightWrite) && !arch.regtyp(&p->to))
return;
// Stop if we jump backward.
// This test is valid because all the NilFlow* are pointers into
+++ /dev/null
-// Copyright 2013 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.
-
-typedef struct Flow Flow;
-typedef struct Graph Graph;
-
-struct Flow {
- Prog* prog; // actual instruction
- Flow* p1; // predecessors of this instruction: p1,
- Flow* p2; // and then p2 linked though p2link.
- Flow* p2link;
- Flow* s1; // successors of this instruction (at most two: s1 and s2).
- Flow* s2;
- Flow* link; // next instruction in function code
-
- int32 active; // usable by client
-
- int32 rpo; // reverse post ordering
- uint16 loop; // x5 for every loop
- uchar refset; // diagnostic generated
-};
-
-struct Graph
-{
- Flow* start;
- int num;
-
- // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
- // and each non-dead Flow node f has g->rpo[f->rpo] == f.
- Flow** rpo;
-};
-
-void fixjmp(Prog*);
-Graph* flowstart(Prog*, int);
-void flowrpo(Graph*);
-void flowend(Graph*);
-void mergetemp(Prog*);
-void nilopt(Prog*);
-int noreturn(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Flow* uniqp(Flow*);
-Flow* uniqs(Flow*);
n->xoffset = 0;
p->pathsym = n->sym;
- gdatastring(n, p->path);
- ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
+ arch.gdatastring(n, p->path);
+ arch.ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
}
static int
dgopkgpath(Sym *s, int ot, Pkg *pkg)
{
if(pkg == nil)
- return dgostringptr(s, ot, nil);
+ return arch.dgostringptr(s, ot, nil);
// Emit reference to go.importpath.""., which 6l will
// rewrite using the correct import path. Every package
if(ns == nil)
ns = pkglookup("importpath.\"\".", mkpkg(strlit("go")));
- return dsymptr(s, ot, ns, 0);
+ return arch.dsymptr(s, ot, ns, 0);
}
dimportpath(pkg);
- return dsymptr(s, ot, pkg->pathsym, 0);
+ return arch.dsymptr(s, ot, pkg->pathsym, 0);
}
/*
// fill in *extraType pointer in header
off = rnd(off, widthptr);
- dsymptr(sym, ptroff, sym, off);
+ arch.dsymptr(sym, ptroff, sym, off);
n = 0;
for(a=m; a; a=a->link) {
ot = off;
s = sym;
if(t->sym) {
- ot = dgostringptr(s, ot, t->sym->name);
+ ot = arch.dgostringptr(s, ot, t->sym->name);
if(t != types[t->etype] && t != errortype)
ot = dgopkgpath(s, ot, t->sym->pkg);
else
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
} else {
- ot = dgostringptr(s, ot, nil);
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
}
// slice header
- ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot + widthptr + 2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(a=m; a; a=a->link) {
// method
// ../../runtime/type.go:/method
- ot = dgostringptr(s, ot, a->name);
+ ot = arch.dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
- ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
- ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->mtype), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->type), 0);
if(a->isym)
- ot = dsymptr(s, ot, a->isym, 0);
+ ot = arch.dsymptr(s, ot, a->isym, 0);
else
ot = duintptr(s, ot, 0);
if(a->tsym)
- ot = dsymptr(s, ot, a->tsym, 0);
+ ot = arch.dsymptr(s, ot, a->tsym, 0);
else
ot = duintptr(s, ot, 0);
}
i |= KindGCProg;
ot = duint8(s, ot, i); // kind
if(algsym == S)
- ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
+ ot = arch.dsymptr(s, ot, algarray, alg*sizeofAlg);
else
- ot = dsymptr(s, ot, algsym, 0);
+ ot = arch.dsymptr(s, ot, algsym, 0);
// gc
if(gcprog) {
gengcprog(t, &gcprog0, &gcprog1);
if(gcprog0 != S)
- ot = dsymptr(s, ot, gcprog0, 0);
+ ot = arch.dsymptr(s, ot, gcprog0, 0);
else
ot = duintptr(s, ot, 0);
- ot = dsymptr(s, ot, gcprog1, 0);
+ ot = arch.dsymptr(s, ot, gcprog1, 0);
} else {
gengcmask(t, gcmask);
x1 = 0;
sbits->flags |= SymUniq;
for(i = 0; i < 2*widthptr; i++)
duint8(sbits, i, gcmask[i]);
- ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
+ arch.ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
}
- ot = dsymptr(s, ot, sbits, 0);
+ ot = arch.dsymptr(s, ot, sbits, 0);
ot = duintptr(s, ot, 0);
}
p = smprint("%-uT", t);
//print("dcommontype: %s\n", p);
- ot = dgostringptr(s, ot, p); // string
+ ot = arch.dgostringptr(s, ot, p); // string
free(p);
// skip pointer to extraType,
// otherwise linker will assume 0.
ot += widthptr;
- ot = dsymptr(s, ot, sptr, 0); // ptrto type
- ot = dsymptr(s, ot, zero, 0); // ptr to zero value
+ ot = arch.dsymptr(s, ot, sptr, 0); // ptrto type
+ ot = arch.dsymptr(s, ot, zero, 0); // ptr to zero value
return ot;
}
s2 = dtypesym(t2);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
- ot = dsymptr(s, ot, s2, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s2, 0);
ot = duintptr(s, ot, t->bound);
} else {
// ../../runtime/type.go:/SliceType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
}
break;
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
ot = duintptr(s, ot, t->chan);
break;
// two slice headers: in and out.
ot = rnd(ot, widthptr);
- ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
+ ot = arch.dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
n = t->thistuple + t->intuple;
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
- ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
+ ot = arch.dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
ot = duintxx(s, ot, t->outtuple, widthint);
ot = duintxx(s, ot, t->outtuple, widthint);
// slice data
for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
break;
case TINTER:
// ../../runtime/type.go:/InterfaceType
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot+widthptr+2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(a=m; a; a=a->link) {
// ../../runtime/type.go:/imethod
- ot = dgostringptr(s, ot, a->name);
+ ot = arch.dgostringptr(s, ot, a->name);
ot = dgopkgpath(s, ot, a->pkg);
- ot = dsymptr(s, ot, dtypesym(a->type), 0);
+ ot = arch.dsymptr(s, ot, dtypesym(a->type), 0);
}
break;
s4 = dtypesym(hmap(t));
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
- ot = dsymptr(s, ot, s2, 0);
- ot = dsymptr(s, ot, s3, 0);
- ot = dsymptr(s, ot, s4, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s2, 0);
+ ot = arch.dsymptr(s, ot, s3, 0);
+ ot = arch.dsymptr(s, ot, s4, 0);
if(t->down->width > MAXKEYSIZE) {
ot = duint8(s, ot, widthptr);
ot = duint8(s, ot, 1); // indirect
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s1, 0);
+ ot = arch.dsymptr(s, ot, s1, 0);
break;
case TSTRUCT:
}
ot = dcommontype(s, ot, t);
xt = ot - 3*widthptr;
- ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
+ ot = arch.dsymptr(s, ot, s, ot+widthptr+2*widthint);
ot = duintxx(s, ot, n, widthint);
ot = duintxx(s, ot, n, widthint);
for(t1=t->type; t1!=T; t1=t1->down) {
// ../../runtime/type.go:/structField
if(t1->sym && !t1->embedded) {
- ot = dgostringptr(s, ot, t1->sym->name);
+ ot = arch.dgostringptr(s, ot, t1->sym->name);
if(exportname(t1->sym->name))
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
else
ot = dgopkgpath(s, ot, t1->sym->pkg);
} else {
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
ot = dgopkgpath(s, ot, localpkg);
else
- ot = dgostringptr(s, ot, nil);
+ ot = arch.dgostringptr(s, ot, nil);
}
- ot = dsymptr(s, ot, dtypesym(t1->type), 0);
- ot = dgostrlitptr(s, ot, t1->note);
+ ot = arch.dsymptr(s, ot, dtypesym(t1->type), 0);
+ ot = arch.dgostrlitptr(s, ot, t1->note);
ot = duintptr(s, ot, t1->width); // field offset
}
break;
}
ot = dextratype(s, ot, t, xt);
- ggloblsym(s, ot, dupok|RODATA);
+ arch.ggloblsym(s, ot, dupok|RODATA);
// generate typelink.foo pointing at s = type.foo.
// The linker will leave a table of all the typelinks for
case TCHAN:
case TMAP:
slink = typelinksym(t);
- dsymptr(slink, 0, s, 0);
- ggloblsym(slink, widthptr, dupok|RODATA);
+ arch.dsymptr(slink, 0, s, 0);
+ arch.ggloblsym(slink, widthptr, dupok|RODATA);
}
}
hashfunc = pkglookup(p, typepkg);
free(p);
ot = 0;
- ot = dsymptr(hashfunc, ot, pkglookup("memhash_varlen", runtimepkg), 0);
+ ot = arch.dsymptr(hashfunc, ot, pkglookup("memhash_varlen", runtimepkg), 0);
ot = duintxx(hashfunc, ot, t->width, widthptr); // size encoded in closure
- ggloblsym(hashfunc, ot, DUPOK|RODATA);
+ arch.ggloblsym(hashfunc, ot, DUPOK|RODATA);
// make equality closure
p = smprint(".eqfunc%lld", t->width);
eqfunc = pkglookup(p, typepkg);
free(p);
ot = 0;
- ot = dsymptr(eqfunc, ot, pkglookup("memequal_varlen", runtimepkg), 0);
+ ot = arch.dsymptr(eqfunc, ot, pkglookup("memequal_varlen", runtimepkg), 0);
ot = duintxx(eqfunc, ot, t->width, widthptr);
- ggloblsym(eqfunc, ot, DUPOK|RODATA);
+ arch.ggloblsym(eqfunc, ot, DUPOK|RODATA);
} else {
// generate an alg table specific to this type
s = typesymprefix(".alg", t);
geneq(eq, t);
// make Go funcs (closures) for calling hash and equal from Go
- dsymptr(hashfunc, 0, hash, 0);
- ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
- dsymptr(eqfunc, 0, eq, 0);
- ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
+ arch.dsymptr(hashfunc, 0, hash, 0);
+ arch.ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
+ arch.dsymptr(eqfunc, 0, eq, 0);
+ arch.ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
}
// ../../runtime/alg.go:/typeAlg
ot = 0;
- ot = dsymptr(s, ot, hashfunc, 0);
- ot = dsymptr(s, ot, eqfunc, 0);
- ggloblsym(s, ot, DUPOK|RODATA);
+ ot = arch.dsymptr(s, ot, hashfunc, 0);
+ ot = arch.dsymptr(s, ot, eqfunc, 0);
+ arch.ggloblsym(s, ot, DUPOK|RODATA);
return s;
}
// Don't generate it if it's too large, runtime will unroll directly into GC bitmap.
if(size <= MaxGCMask) {
gc0 = typesymprefix(".gc", t);
- ggloblsym(gc0, size, DUPOK|NOPTR);
+ arch.ggloblsym(gc0, size, DUPOK|NOPTR);
*pgc0 = gc0;
}
xoffset = 0;
gengcprog1(&g, t, &xoffset);
ot = proggenfini(&g);
- ggloblsym(gc1, ot, DUPOK|RODATA);
+ arch.ggloblsym(gc1, ot, DUPOK|RODATA);
*pgc1 = gc1;
}
case OLITERAL:
if(iszero(r))
return 1;
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
case OADDR:
switch(r->left->op) {
case ONAME:
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
}
break;
case OSTRUCTLIT:
case OMAPLIT:
// copy pointer
- gdata(l, nod(OADDR, r->nname, N), l->type->width);
+ arch.gdata(l, nod(OADDR, r->nname, N), l->type->width);
return 1;
}
break;
a = r->nname;
n1 = *l;
n1.xoffset = l->xoffset + Array_array;
- gdata(&n1, nod(OADDR, a, N), widthptr);
+ arch.gdata(&n1, nod(OADDR, a, N), widthptr);
n1.xoffset = l->xoffset + Array_nel;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
n1.xoffset = l->xoffset + Array_cap;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
return 1;
}
// fall through
n1.xoffset = l->xoffset + e->xoffset;
n1.type = e->expr->type;
if(e->expr->op == OLITERAL)
- gdata(&n1, e->expr, n1.type->width);
+ arch.gdata(&n1, e->expr, n1.type->width);
else {
ll = nod(OXXX, N, N);
*ll = n1;
case OLITERAL:
if(iszero(r))
return 1;
- gdata(l, r, l->type->width);
+ arch.gdata(l, r, l->type->width);
return 1;
case OADDR:
if(stataddr(&nam, r->left)) {
n1 = *r;
n1.left = &nam;
- gdata(l, &n1, l->type->width);
+ arch.gdata(l, &n1, l->type->width);
return 1;
}
// Init pointer.
a = staticname(r->left->type, 1);
r->nname = a;
- gdata(l, nod(OADDR, a, N), l->type->width);
+ arch.gdata(l, nod(OADDR, a, N), l->type->width);
// Init underlying literal.
if(!staticassign(a, r->left, out))
*out = list(*out, nod(OAS, a, r->left));
r->nname = a;
n1 = *l;
n1.xoffset = l->xoffset + Array_array;
- gdata(&n1, nod(OADDR, a, N), widthptr);
+ arch.gdata(&n1, nod(OADDR, a, N), widthptr);
n1.xoffset = l->xoffset + Array_nel;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
n1.xoffset = l->xoffset + Array_cap;
- gdata(&n1, r->right, widthint);
+ arch.gdata(&n1, r->right, widthint);
// Fall through to init underlying array.
l = a;
}
n1.xoffset = l->xoffset + e->xoffset;
n1.type = e->expr->type;
if(e->expr->op == OLITERAL)
- gdata(&n1, e->expr, n1.type->width);
+ arch.gdata(&n1, e->expr, n1.type->width);
else {
a = nod(OXXX, N, N);
*a = n1;
if(l < 0)
break;
// Check for overflow.
- if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
+ if(n->type->width != 0 && arch.MAXWIDTH/n->type->width <= l)
break;
nam->xoffset += l*n->type->width;
nam->type = n->type;
case TPTR64:
case TFLOAT32:
case TFLOAT64:
- gdata(&nam, nr, nr->type->width);
+ arch.gdata(&nam, nr, nr->type->width);
break;
case TCOMPLEX64:
case TCOMPLEX128:
- gdatacomplex(&nam, nr->val.u.cval);
+ arch.gdatacomplex(&nam, nr->val.u.cval);
break;
case TSTRING:
- gdatastring(&nam, nr->val.u.sval);
+ arch.gdatastring(&nam, nr->val.u.sval);
break;
}
return 1;
slice:
- gused(N); // in case the data is the dest of a goto
+ arch.gused(N); // in case the data is the dest of a goto
nl = nr;
if(nr == N || nr->op != OADDR)
goto no;
goto no;
nam.xoffset += Array_array;
- gdata(&nam, nl, types[tptr]->width);
+ arch.gdata(&nam, nl, types[tptr]->width);
nam.xoffset += Array_nel-Array_array;
nodconst(&nod1, types[TINT], nr->type->bound);
- gdata(&nam, &nod1, widthint);
+ arch.gdata(&nam, &nod1, widthint);
nam.xoffset += Array_cap-Array_nel;
- gdata(&nam, &nod1, widthint);
+ arch.gdata(&nam, &nod1, widthint);
goto yes;
dowidth(t);
w = t->argwid;
- if(w >= MAXWIDTH)
+ if(w >= arch.MAXWIDTH)
fatal("bad argwid %T", t);
w += extra;
- if(w >= MAXWIDTH)
+ if(w >= arch.MAXWIDTH)
fatal("bad argwid %d + %T", extra, t);
if(w > maxarg)
maxarg = w;
l->class = PEXTERN;
l->xoffset = 0;
sym->def = l;
- ggloblsym(sym, widthptr, DUPOK|NOPTR);
+ arch.ggloblsym(sym, widthptr, DUPOK|NOPTR);
}
l = nod(OADDR, sym->def, N);
l->addable = 1;
case OCONV:
case OCONVNOP:
- if(thechar == '5') {
+ if(arch.thechar == '5') {
if(isfloat[n->left->type->etype]) {
if(n->type->etype == TINT64) {
n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
l = tmp;
}
- a = nod(OAS, l, nodarg(r, fp));
+ a = nod(OAS, l, arch.nodarg(r, fp));
a = convas(a, init);
ullmancalc(a);
if(a->ullman >= UINF) {
walkexpr(&n, init);
}
- a = nod(OAS, nodarg(l, fp), n);
+ a = nod(OAS, arch.nodarg(l, fp), n);
nn = list(nn, convas(a, init));
return nn;
}
if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
// optimization - can do block copy
if(eqtypenoname(r->type, *nl)) {
- a = nodarg(*nl, fp);
+ a = arch.nodarg(*nl, fp);
r = nod(OCONVNOP, r, N);
r->type = a->type;
nn = list1(convas(nod(OAS, a, r), init));
// argument to a ddd parameter then it is
// passed thru unencapsulated
if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
- a = nod(OAS, nodarg(l, fp), r);
+ a = nod(OAS, arch.nodarg(l, fp), r);
a = convas(a, init);
nn = list(nn, a);
goto ret;
goto ret;
}
- a = nod(OAS, nodarg(l, fp), r);
+ a = nod(OAS, arch.nodarg(l, fp), r);
a = convas(a, init);
nn = list(nn, a);
// Defer might stop a panic and show the
// return values as they exist at the time of panic.
// Make sure to zero them on entry to the function.
- nn = list(nn, nod(OAS, nodarg(t, 1), N));
+ nn = list(nn, nod(OAS, arch.nodarg(t, 1), N));
}
if(v == N || !(v->class & PHEAP))
continue;
Node *l, *r;
Node *n;
- if(thechar == '9')
+ if(arch.thechar == '9')
return;
n = *np;
Magic m;
// TODO(minux)
- if(thechar == '9')
+ if(arch.thechar == '9')
return;
n = *np;