mirror of
https://github.com/golang/go.git
synced 2025-05-31 23:25:39 +00:00
[dev.garbage] all: merge dev.cc into dev.garbage
The garbage collector is now written in Go. There is plenty to clean up (just like on dev.cc). all.bash passes on darwin/amd64, darwin/386, linux/amd64, linux/386. TBR=rlh R=austin, rlh, bradfitz CC=golang-codereviews https://golang.org/cl/173250043
This commit is contained in:
commit
0fcf54b3d2
@ -89,7 +89,7 @@ struct Prog
|
||||
int32 lineno;
|
||||
Prog* link;
|
||||
short as;
|
||||
uchar scond; // arm only
|
||||
uchar scond; // arm only; condition codes
|
||||
|
||||
// operands
|
||||
Addr from;
|
||||
|
@ -1,5 +0,0 @@
|
||||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../Make.dist
|
1213
src/cmd/5c/cgen.c
1213
src/cmd/5c/cgen.c
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
|
||||
5c is a version of the Plan 9 C compiler. The original is documented at
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/1/8c
|
||||
|
||||
Its target architecture is the ARM, referred to by these tools as arm.
|
||||
|
||||
*/
|
||||
package main
|
333
src/cmd/5c/gc.h
333
src/cmd/5c/gc.h
@ -1,333 +0,0 @@
|
||||
// Inferno utils/5c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/5c/gc.h
|
||||
//
|
||||
// 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 "../cc/cc.h"
|
||||
#include "../5l/5.out.h"
|
||||
|
||||
/*
|
||||
* 5c/arm
|
||||
* Arm 7500
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 4
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Multab Multab;
|
||||
typedef struct Hintab Hintab;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
|
||||
#define R0ISZERO 0
|
||||
|
||||
#define A ((Addr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
int32 val;
|
||||
int32 label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
int32 val;
|
||||
int32 label;
|
||||
};
|
||||
|
||||
struct Multab
|
||||
{
|
||||
int32 val;
|
||||
char code[20];
|
||||
};
|
||||
|
||||
struct Hintab
|
||||
{
|
||||
ushort val;
|
||||
char hint[10];
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
int32 pc;
|
||||
int32 rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu;
|
||||
int32 loop; /* could be shorter */
|
||||
|
||||
|
||||
Reg* log5;
|
||||
int32 active;
|
||||
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 breakpc;
|
||||
EXTERN int32 nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN int32 continpc;
|
||||
EXTERN int32 curarg;
|
||||
EXTERN int32 cursafe;
|
||||
EXTERN int32 isbigendian;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN int32 maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Multab multab[20];
|
||||
extern int hintabsize;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN int32 nrathole;
|
||||
EXTERN int32 nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN int32 pc;
|
||||
EXTERN Node regnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN char reg[NREG+NFREG];
|
||||
EXTERN int32 exregoffset;
|
||||
EXTERN int32 exfregoffset;
|
||||
EXTERN int suppress;
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 4
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN int32* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN int32 maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
extern Hintab hintab[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void noretval(int);
|
||||
void usedset(Node*, int);
|
||||
void xcom(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
Prog* gtext(Sym*, int32);
|
||||
vlong argsize(int);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, int32);
|
||||
void layout(Node*, Node*, int, int, Node*);
|
||||
void cgenrel(Node*, Node*);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(int32);
|
||||
Node* nod32const(vlong);
|
||||
Node* nodfconst(double);
|
||||
void nodreg(Node*, Node*, int);
|
||||
void regret(Node*, Node*, Type*, int);
|
||||
int tmpreg(void);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void raddr(Node*, Prog*);
|
||||
void naddr(Node*, Addr*);
|
||||
void gmovm(Node*, Node*, int);
|
||||
void gmove(Node*, Node*);
|
||||
void gmover(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Node*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, int32);
|
||||
int sconst(Node*);
|
||||
int sval(int32);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
void gprefetch(Node*);
|
||||
void gpcdata(int, int);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, int32, Node*);
|
||||
void swit2(C1*, int, int32, Node*);
|
||||
void newcase(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
int mulcon(Node*, Node*);
|
||||
Multab* mulcon0(int32);
|
||||
void nullwarn(Node*, Node*);
|
||||
void outcode(void);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Addr*, int);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void addreg(Addr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Addr*);
|
||||
int regzer(Addr*);
|
||||
int anyvar(Addr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int shiftprop(Reg*);
|
||||
void constprop(Addr*, Addr*, Reg*);
|
||||
int copy1(Addr*, Addr*, Reg*, int);
|
||||
int copyu(Prog*, Addr*, Addr*);
|
||||
|
||||
int copyas(Addr*, Addr*);
|
||||
int copyau(Addr*, Addr*);
|
||||
int copyau1(Prog*, Addr*);
|
||||
int copysub(Addr*, Addr*, Addr*, int);
|
||||
int copysub1(Prog*, Addr*, Addr*, int);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
|
||||
void predicate(void);
|
||||
int isbranch(Prog *);
|
||||
int predicable(Prog *p);
|
||||
int modifiescpsr(Prog *p);
|
@ -1,39 +0,0 @@
|
||||
// Inferno utils/5c/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.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.
|
||||
|
||||
|
||||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
listinit5();
|
||||
}
|
640
src/cmd/5c/mul.c
640
src/cmd/5c/mul.c
@ -1,640 +0,0 @@
|
||||
// Inferno utils/5c/mul.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/5c/mul.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 "gc.h"
|
||||
|
||||
/*
|
||||
* code sequences for multiply by constant.
|
||||
* [a-l][0-3]
|
||||
* lsl $(A-'a'),r0,r1
|
||||
* [+][0-7]
|
||||
* add r0,r1,r2
|
||||
* [-][0-7]
|
||||
* sub r0,r1,r2
|
||||
*/
|
||||
|
||||
static int maxmulops = 3; /* max # of ops to replace mul with */
|
||||
static int multabp;
|
||||
static int32 mulval;
|
||||
static char* mulcp;
|
||||
static int32 valmax;
|
||||
static int shmax;
|
||||
|
||||
static int docode(char *hp, char *cp, int r0, int r1);
|
||||
static int gen1(int len);
|
||||
static int gen2(int len, int32 r1);
|
||||
static int gen3(int len, int32 r0, int32 r1, int flag);
|
||||
enum
|
||||
{
|
||||
SR1 = 1<<0, /* r1 has been shifted */
|
||||
SR0 = 1<<1, /* r0 has been shifted */
|
||||
UR1 = 1<<2, /* r1 has not been used */
|
||||
UR0 = 1<<3, /* r0 has not been used */
|
||||
};
|
||||
|
||||
Multab*
|
||||
mulcon0(int32 v)
|
||||
{
|
||||
int a1, a2, g;
|
||||
Multab *m, *m1;
|
||||
char hint[10];
|
||||
|
||||
if(v < 0)
|
||||
v = -v;
|
||||
|
||||
/*
|
||||
* look in cache
|
||||
*/
|
||||
m = multab;
|
||||
for(g=0; g<nelem(multab); g++) {
|
||||
if(m->val == v) {
|
||||
if(m->code[0] == 0)
|
||||
return 0;
|
||||
return m;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
/*
|
||||
* select a spot in cache to overwrite
|
||||
*/
|
||||
multabp++;
|
||||
if(multabp < 0 || multabp >= nelem(multab))
|
||||
multabp = 0;
|
||||
m = multab+multabp;
|
||||
m->val = v;
|
||||
mulval = v;
|
||||
|
||||
/*
|
||||
* look in execption hint table
|
||||
*/
|
||||
a1 = 0;
|
||||
a2 = hintabsize;
|
||||
for(;;) {
|
||||
if(a1 >= a2)
|
||||
goto no;
|
||||
g = (a2 + a1)/2;
|
||||
if(v < hintab[g].val) {
|
||||
a2 = g;
|
||||
continue;
|
||||
}
|
||||
if(v > hintab[g].val) {
|
||||
a1 = g+1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(docode(hintab[g].hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("multiply table failure %d\n", v);
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
|
||||
no:
|
||||
/*
|
||||
* try to search
|
||||
*/
|
||||
hint[0] = 0;
|
||||
for(g=1; g<=maxmulops; g++) {
|
||||
if(g >= maxmulops && v >= 65535)
|
||||
break;
|
||||
mulcp = hint+g;
|
||||
*mulcp = 0;
|
||||
if(gen1(g)) {
|
||||
if(docode(hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("multiply table failure %d\n", v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* try a recur followed by a shift
|
||||
*/
|
||||
g = 0;
|
||||
while(!(v & 1)) {
|
||||
g++;
|
||||
v >>= 1;
|
||||
}
|
||||
if(g) {
|
||||
m1 = mulcon0(v);
|
||||
if(m1) {
|
||||
strcpy(m->code, m1->code);
|
||||
sprint(strchr(m->code, 0), "%c0", g+'a');
|
||||
return m;
|
||||
}
|
||||
}
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
docode(char *hp, char *cp, int r0, int r1)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
c = *hp++;
|
||||
*cp = c;
|
||||
cp += 2;
|
||||
switch(c) {
|
||||
default:
|
||||
c -= 'a';
|
||||
if(c < 1 || c >= 30)
|
||||
break;
|
||||
for(i=0; i<4; i++) {
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(docode(hp, cp, r0<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 1:
|
||||
if(docode(hp, cp, r1<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r0, r0<<c))
|
||||
goto out;
|
||||
break;
|
||||
case 3:
|
||||
if(docode(hp, cp, r0, r1<<c))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0+r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0+r1))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0-r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r1-r0, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0-r1))
|
||||
goto out;
|
||||
break;
|
||||
case 6:
|
||||
if(docode(hp, cp, r0, r1-r0))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if(r0 == mulval)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
cp[-1] = i+'0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen1(int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(shmax=1; shmax<30; shmax++) {
|
||||
valmax = 1<<shmax;
|
||||
if(valmax >= mulval)
|
||||
break;
|
||||
}
|
||||
if(mulval == 1)
|
||||
return 1;
|
||||
|
||||
len--;
|
||||
for(i=1; i<=shmax; i++)
|
||||
if(gen2(len, 1<<i)) {
|
||||
*--mulcp = 'a'+i;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gen2(int len, int32 r1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(len <= 0) {
|
||||
if(r1 == mulval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(gen3(len, r1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, r1-1, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1-1, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
if(mulval == r1+1) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-1) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen3(int len, int32 r0, int32 r1, int flag)
|
||||
{
|
||||
int i, f1, f2;
|
||||
int32 x;
|
||||
|
||||
if(r0 <= 0 ||
|
||||
r0 >= r1 ||
|
||||
r1 > valmax)
|
||||
return 0;
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(!(flag & UR1)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & UR0)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r1, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR1)) {
|
||||
f1 = UR1|SR1|(flag&UR0);
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR0)) {
|
||||
f1 = UR0|SR0|(flag&(SR1|UR1));
|
||||
|
||||
f2 = UR1|SR1;
|
||||
if(flag & UR1)
|
||||
f2 |= UR0;
|
||||
if(flag & SR1)
|
||||
f2 |= SR0;
|
||||
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(x > r1) {
|
||||
if(gen3(len, r1, x, f2)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r1, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = r1+r0;
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(gen3(len, r1, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
x = r1-r0;
|
||||
if(gen3(len, x, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(x > r0) {
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r0, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
f1 = flag & (UR0|UR1);
|
||||
if(f1 == UR1) {
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x >= mulval) {
|
||||
if(x == mulval) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mulval == r1+r0) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-r0) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* hint table has numbers that
|
||||
* the search algorithm fails on.
|
||||
* <1000:
|
||||
* all numbers
|
||||
* <5000:
|
||||
* ÷ by 5
|
||||
* <10000:
|
||||
* ÷ by 50
|
||||
* <65536:
|
||||
* ÷ by 250
|
||||
*/
|
||||
Hintab hintab[] =
|
||||
{
|
||||
683, "b++d+e+",
|
||||
687, "b+e++e-",
|
||||
691, "b++d+e+",
|
||||
731, "b++d+e+",
|
||||
811, "b++d+i+",
|
||||
821, "b++e+e+",
|
||||
843, "b+d++e+",
|
||||
851, "b+f-+e-",
|
||||
853, "b++e+e+",
|
||||
877, "c++++g-",
|
||||
933, "b+c++g-",
|
||||
981, "c-+e-d+",
|
||||
1375, "b+c+b+h-",
|
||||
1675, "d+b++h+",
|
||||
2425, "c++f-e+",
|
||||
2675, "c+d++f-",
|
||||
2750, "b+d-b+h-",
|
||||
2775, "c-+g-e-",
|
||||
3125, "b++e+g+",
|
||||
3275, "b+c+g+e+",
|
||||
3350, "c++++i+",
|
||||
3475, "c-+e-f-",
|
||||
3525, "c-+d+g-",
|
||||
3625, "c-+e-j+",
|
||||
3675, "b+d+d+e+",
|
||||
3725, "b+d-+h+",
|
||||
3925, "b+d+f-d-",
|
||||
4275, "b+g++e+",
|
||||
4325, "b+h-+d+",
|
||||
4425, "b+b+g-j-",
|
||||
4525, "b+d-d+f+",
|
||||
4675, "c++d-g+",
|
||||
4775, "b+d+b+g-",
|
||||
4825, "c+c-+i-",
|
||||
4850, "c++++i-",
|
||||
4925, "b++e-g-",
|
||||
4975, "c+f++e-",
|
||||
5500, "b+g-c+d+",
|
||||
6700, "d+b++i+",
|
||||
9700, "d++++j-",
|
||||
11000, "b+f-c-h-",
|
||||
11750, "b+d+g+j-",
|
||||
12500, "b+c+e-k+",
|
||||
13250, "b+d+e-f+",
|
||||
13750, "b+h-c-d+",
|
||||
14250, "b+g-c+e-",
|
||||
14500, "c+f+j-d-",
|
||||
14750, "d-g--f+",
|
||||
16750, "b+e-d-n+",
|
||||
17750, "c+h-b+e+",
|
||||
18250, "d+b+h-d+",
|
||||
18750, "b+g-++f+",
|
||||
19250, "b+e+b+h+",
|
||||
19750, "b++h--f-",
|
||||
20250, "b+e-l-c+",
|
||||
20750, "c++bi+e-",
|
||||
21250, "b+i+l+c+",
|
||||
22000, "b+e+d-g-",
|
||||
22250, "b+d-h+k-",
|
||||
22750, "b+d-e-g+",
|
||||
23250, "b+c+h+e-",
|
||||
23500, "b+g-c-g-",
|
||||
23750, "b+g-b+h-",
|
||||
24250, "c++g+m-",
|
||||
24750, "b+e+e+j-",
|
||||
25000, "b++dh+g+",
|
||||
25250, "b+e+d-g-",
|
||||
25750, "b+e+b+j+",
|
||||
26250, "b+h+c+e+",
|
||||
26500, "b+h+c+g+",
|
||||
26750, "b+d+e+g-",
|
||||
27250, "b+e+e+f+",
|
||||
27500, "c-i-c-d+",
|
||||
27750, "b+bd++j+",
|
||||
28250, "d-d-++i-",
|
||||
28500, "c+c-h-e-",
|
||||
29000, "b+g-d-f+",
|
||||
29500, "c+h+++e-",
|
||||
29750, "b+g+f-c+",
|
||||
30250, "b+f-g-c+",
|
||||
33500, "c-f-d-n+",
|
||||
33750, "b+d-b+j-",
|
||||
34250, "c+e+++i+",
|
||||
35250, "e+b+d+k+",
|
||||
35500, "c+e+d-g-",
|
||||
35750, "c+i-++e+",
|
||||
36250, "b+bh-d+e+",
|
||||
36500, "c+c-h-e-",
|
||||
36750, "d+e--i+",
|
||||
37250, "b+g+g+b+",
|
||||
37500, "b+h-b+f+",
|
||||
37750, "c+be++j-",
|
||||
38500, "b+e+b+i+",
|
||||
38750, "d+i-b+d+",
|
||||
39250, "b+g-l-+d+",
|
||||
39500, "b+g-c+g-",
|
||||
39750, "b+bh-c+f-",
|
||||
40250, "b+bf+d+g-",
|
||||
40500, "b+g-c+g+",
|
||||
40750, "c+b+i-e+",
|
||||
41250, "d++bf+h+",
|
||||
41500, "b+j+c+d-",
|
||||
41750, "c+f+b+h-",
|
||||
42500, "c+h++g+",
|
||||
42750, "b+g+d-f-",
|
||||
43250, "b+l-e+d-",
|
||||
43750, "c+bd+h+f-",
|
||||
44000, "b+f+g-d-",
|
||||
44250, "b+d-g--f+",
|
||||
44500, "c+e+c+h+",
|
||||
44750, "b+e+d-h-",
|
||||
45250, "b++g+j-g+",
|
||||
45500, "c+d+e-g+",
|
||||
45750, "b+d-h-e-",
|
||||
46250, "c+bd++j+",
|
||||
46500, "b+d-c-j-",
|
||||
46750, "e-e-b+g-",
|
||||
47000, "b+c+d-j-",
|
||||
47250, "b+e+e-g-",
|
||||
47500, "b+g-c-h-",
|
||||
47750, "b+f-c+h-",
|
||||
48250, "d--h+n-",
|
||||
48500, "b+c-g+m-",
|
||||
48750, "b+e+e-g+",
|
||||
49500, "c-f+e+j-",
|
||||
49750, "c+c+g++f-",
|
||||
50000, "b+e+e+k+",
|
||||
50250, "b++i++g+",
|
||||
50500, "c+g+f-i+",
|
||||
50750, "b+e+d+k-",
|
||||
51500, "b+i+c-f+",
|
||||
51750, "b+bd+g-e-",
|
||||
52250, "b+d+g-j+",
|
||||
52500, "c+c+f+g+",
|
||||
52750, "b+c+e+i+",
|
||||
53000, "b+i+c+g+",
|
||||
53500, "c+g+g-n+",
|
||||
53750, "b+j+d-c+",
|
||||
54250, "b+d-g-j-",
|
||||
54500, "c-f+e+f+",
|
||||
54750, "b+f-+c+g+",
|
||||
55000, "b+g-d-g-",
|
||||
55250, "b+e+e+g+",
|
||||
55500, "b+cd++j+",
|
||||
55750, "b+bh-d-f-",
|
||||
56250, "c+d-b+j-",
|
||||
56500, "c+d+c+i+",
|
||||
56750, "b+e+d++h-",
|
||||
57000, "b+d+g-f+",
|
||||
57250, "b+f-m+d-",
|
||||
57750, "b+i+c+e-",
|
||||
58000, "b+e+d+h+",
|
||||
58250, "c+b+g+g+",
|
||||
58750, "d-e-j--e+",
|
||||
59000, "d-i-+e+",
|
||||
59250, "e--h-m+",
|
||||
59500, "c+c-h+f-",
|
||||
59750, "b+bh-e+i-",
|
||||
60250, "b+bh-e-e-",
|
||||
60500, "c+c-g-g-",
|
||||
60750, "b+e-l-e-",
|
||||
61250, "b+g-g-c+",
|
||||
61750, "b+g-c+g+",
|
||||
62250, "f--+c-i-",
|
||||
62750, "e+f--+g+",
|
||||
64750, "b+f+d+p-",
|
||||
};
|
||||
int hintabsize = nelem(hintab);
|
1478
src/cmd/5c/peep.c
1478
src/cmd/5c/peep.c
File diff suppressed because it is too large
Load Diff
1210
src/cmd/5c/reg.c
1210
src/cmd/5c/reg.c
File diff suppressed because it is too large
Load Diff
@ -1,265 +0,0 @@
|
||||
// Inferno utils/5c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/5c/sgen.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 "gc.h"
|
||||
|
||||
Prog*
|
||||
gtext(Sym *s, int32 stkoff)
|
||||
{
|
||||
int32 a;
|
||||
|
||||
a = argsize(1);
|
||||
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
|
||||
yyerror("stack frame too large for NOSPLIT function");
|
||||
|
||||
gpseudo(ATEXT, s, nodconst(stkoff));
|
||||
p->to.type = D_CONST2;
|
||||
p->to.offset2 = a;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = D_REG;
|
||||
p->to.reg = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = D_FREG;
|
||||
p->to.reg = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* CONST ==> 20 $value
|
||||
* NAME ==> 10 name
|
||||
* REGISTER ==> 11 register
|
||||
* INDREG ==> 12 *[(reg)+offset]
|
||||
* &10 ==> 2 $name
|
||||
* ADD(2, 20) ==> 2 $name+offset
|
||||
* ADD(3, 20) ==> 3 $(reg)+offset
|
||||
* &12 ==> 3 $(reg)+offset
|
||||
* *11 ==> 11 ??
|
||||
* *2 ==> 10 name
|
||||
* *3 ==> 12 *(reg)+offset
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int t;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->addable = 0;
|
||||
n->complex = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
return;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 11;
|
||||
return;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
return;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 10;
|
||||
return;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 2;
|
||||
if(l->addable == 12)
|
||||
n->addable = 3;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->addable == 11)
|
||||
n->addable = 12;
|
||||
if(l->addable == 3)
|
||||
n->addable = 12;
|
||||
if(l->addable == 2)
|
||||
n->addable = 10;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(l->addable == 20) {
|
||||
if(r->addable == 2)
|
||||
n->addable = 2;
|
||||
if(r->addable == 3)
|
||||
n->addable = 3;
|
||||
}
|
||||
if(r->addable == 20) {
|
||||
if(l->addable == 2)
|
||||
n->addable = 2;
|
||||
if(l->addable == 3)
|
||||
n->addable = 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMUL:
|
||||
case OASMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
t = vlog(l);
|
||||
if(t >= 0) {
|
||||
n->op = OASHL;
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
r = l;
|
||||
l = n->left;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
if(t >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
if(com64(n))
|
||||
return;
|
||||
|
||||
switch(n->op) {
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OEQ:
|
||||
case ONE:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
461
src/cmd/5c/swt.c
461
src/cmd/5c/swt.c
@ -1,461 +0,0 @@
|
||||
// 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 "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
Node nreg;
|
||||
|
||||
if(typev[n->type->etype]) {
|
||||
regsalloc(&nreg, n);
|
||||
nreg.type = types[TVLONG];
|
||||
cgen(n, &nreg);
|
||||
swit2(q, nc, def, &nreg);
|
||||
return;
|
||||
}
|
||||
|
||||
regalloc(&nreg, n, Z);
|
||||
nreg.type = types[TLONG];
|
||||
cgen(n, &nreg);
|
||||
swit2(q, nc, def, &nreg);
|
||||
regfree(&nreg);
|
||||
}
|
||||
|
||||
void
|
||||
swit2(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
int32 v;
|
||||
Prog *sp;
|
||||
|
||||
if(nc >= 3) {
|
||||
i = (q+nc-1)->val - (q+0)->val;
|
||||
if(!nacl && i > 0 && i < nc*2)
|
||||
goto direct;
|
||||
}
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8ux\n", q->val);
|
||||
gopcode(OEQ, nodconst(q->val), n, Z);
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8ux\n", r->val);
|
||||
gopcode(OGT, nodconst(r->val), n, Z);
|
||||
sp = p;
|
||||
gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */
|
||||
patch(p, r->label);
|
||||
swit2(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8ux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n);
|
||||
return;
|
||||
|
||||
direct:
|
||||
v = q->val;
|
||||
if(v != 0)
|
||||
gopcode(OSUB, nodconst(v), Z, n);
|
||||
gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
|
||||
patch(p, def);
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8ux\n", q->val);
|
||||
while(q->val != v) {
|
||||
nextpc();
|
||||
p->as = ABCASE;
|
||||
patch(p, def);
|
||||
v++;
|
||||
}
|
||||
nextpc();
|
||||
p->as = ABCASE;
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
v++;
|
||||
}
|
||||
gbranch(OGOTO); /* so that regopt() won't be confused */
|
||||
patch(p, def);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
int32 v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gopcode(OAS, n2, Z, n3);
|
||||
gopcode(OAS, n3, Z, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, nodconst(v), Z, n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, nodconst(sh), Z, n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, nodconst(sh), Z, n1);
|
||||
else
|
||||
gopcode(OASHR, nodconst(sh), Z, n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int32 v;
|
||||
Node nod, *l;
|
||||
int sh;
|
||||
|
||||
/*
|
||||
* n1 has adjusted/masked value
|
||||
* n2 has address of cell
|
||||
* n3 has contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
regalloc(&nod, l, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, nodconst(v), Z, n1);
|
||||
gopcode(OAS, n1, Z, &nod);
|
||||
if(nn != Z)
|
||||
gopcode(OAS, n1, Z, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, nodconst(sh), Z, &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, nodconst(~v), Z, n3);
|
||||
gopcode(OOR, n3, Z, &nod);
|
||||
gopcode(OAS, &nod, Z, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
int32
|
||||
outstring(char *s, int32 n)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->reg = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
mulcon(Node *n, Node *nn)
|
||||
{
|
||||
Node *l, *r, nod1, nod2;
|
||||
Multab *m;
|
||||
int32 v, vs;
|
||||
int o;
|
||||
char code[sizeof(m->code)+2], *p;
|
||||
|
||||
if(typefd[n->type->etype])
|
||||
return 0;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->op == OCONST) {
|
||||
l = r;
|
||||
r = n->left;
|
||||
}
|
||||
if(r->op != OCONST)
|
||||
return 0;
|
||||
v = convvtox(r->vconst, n->type->etype);
|
||||
if(v != r->vconst) {
|
||||
if(debug['M'])
|
||||
print("%L multiply conv: %lld\n", n->lineno, r->vconst);
|
||||
return 0;
|
||||
}
|
||||
m = mulcon0(v);
|
||||
if(!m) {
|
||||
if(debug['M'])
|
||||
print("%L multiply table: %lld\n", n->lineno, r->vconst);
|
||||
return 0;
|
||||
}
|
||||
if(debug['M'] && debug['v'])
|
||||
print("%L multiply: %d\n", n->lineno, v);
|
||||
|
||||
memmove(code, m->code, sizeof(m->code));
|
||||
code[sizeof(m->code)] = 0;
|
||||
|
||||
p = code;
|
||||
if(p[1] == 'i')
|
||||
p += 2;
|
||||
regalloc(&nod1, n, nn);
|
||||
cgen(l, &nod1);
|
||||
vs = v;
|
||||
regalloc(&nod2, n, Z);
|
||||
|
||||
loop:
|
||||
switch(*p) {
|
||||
case 0:
|
||||
regfree(&nod2);
|
||||
if(vs < 0) {
|
||||
gopcode(OAS, &nod1, Z, &nod1);
|
||||
gopcode(OSUB, &nod1, nodconst(0), nn);
|
||||
} else
|
||||
gopcode(OAS, &nod1, Z, nn);
|
||||
regfree(&nod1);
|
||||
return 1;
|
||||
case '+':
|
||||
o = OADD;
|
||||
goto addsub;
|
||||
case '-':
|
||||
o = OSUB;
|
||||
addsub: /* number is r,n,l */
|
||||
v = p[1] - '0';
|
||||
r = &nod1;
|
||||
if(v&4)
|
||||
r = &nod2;
|
||||
n = &nod1;
|
||||
if(v&2)
|
||||
n = &nod2;
|
||||
l = &nod1;
|
||||
if(v&1)
|
||||
l = &nod2;
|
||||
gopcode(o, l, n, r);
|
||||
break;
|
||||
default: /* op is shiftcount, number is r,l */
|
||||
v = p[1] - '0';
|
||||
r = &nod1;
|
||||
if(v&2)
|
||||
r = &nod2;
|
||||
l = &nod1;
|
||||
if(v&1)
|
||||
l = &nod2;
|
||||
v = *p - 'a';
|
||||
if(v < 0 || v >= 32) {
|
||||
diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
|
||||
break;
|
||||
}
|
||||
gopcode(OASHL, nodconst(v), l, r);
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
int32 e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0));
|
||||
p->from.offset += o+e;
|
||||
p->reg = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
|
||||
if(a->op == OCONST && typev[a->type->etype]) {
|
||||
if(isbigendian)
|
||||
gpseudo(ADATA, s, nod32const(a->vconst>>32));
|
||||
else
|
||||
gpseudo(ADATA, s, nod32const(a->vconst));
|
||||
p->from.offset += o;
|
||||
p->reg = 4;
|
||||
if(isbigendian)
|
||||
gpseudo(ADATA, s, nod32const(a->vconst));
|
||||
else
|
||||
gpseudo(ADATA, s, nod32const(a->vconst>>32));
|
||||
p->from.offset += o + 4;
|
||||
p->reg = 4;
|
||||
return;
|
||||
}
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->reg = w;
|
||||
if(p->to.type == D_OREG)
|
||||
p->to.type = D_CONST;
|
||||
}
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
|
||||
if(pragcgobuf.to > pragcgobuf.start) {
|
||||
Bprint(&outbuf, "\n");
|
||||
Bprint(&outbuf, "$$ // exports\n\n");
|
||||
Bprint(&outbuf, "$$ // local types\n\n");
|
||||
Bprint(&outbuf, "$$ // cgo\n");
|
||||
Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
|
||||
Bprint(&outbuf, "\n$$\n\n");
|
||||
}
|
||||
Bprint(&outbuf, "!\n");
|
||||
|
||||
writeobj(ctxt, &outbuf);
|
||||
lastp = P;
|
||||
}
|
||||
|
||||
int32
|
||||
align(int32 i, Type *t, int op, int32 *maxalign)
|
||||
{
|
||||
int32 o;
|
||||
Type *v;
|
||||
int w, packw;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
packw = 0;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = *maxalign;
|
||||
if(w < 1)
|
||||
w = 1;
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
if(v->etype == TSTRUCT || v->etype == TUNION)
|
||||
w = v->align;
|
||||
else {
|
||||
w = ewidth[v->etype];
|
||||
if(w == 8)
|
||||
w = 4;
|
||||
}
|
||||
if(w < 1 || w > SZ_LONG)
|
||||
fatal(Z, "align");
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesuv[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1, nil);
|
||||
o = align(o, types[TIND], Aarg2, nil);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_LONG) {
|
||||
w = SZ_LONG;
|
||||
break;
|
||||
}
|
||||
w = 1; /* little endian no adjustment */
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
w = t->width;
|
||||
if(w > SZ_LONG)
|
||||
w = SZ_LONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total align of automatic */
|
||||
o = align(o, t, Ael2, nil);
|
||||
o = align(o, t, Ael1, nil);
|
||||
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
|
||||
break;
|
||||
}
|
||||
if(packw != 0 && xround(o, w) != xround(o, packw))
|
||||
diag(Z, "#pragma pack changes offset of %T", t);
|
||||
o = xround(o, w);
|
||||
if(maxalign != nil && *maxalign < w)
|
||||
*maxalign = w;
|
||||
if(debug['A'])
|
||||
print("align %s %d %T = %d\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int32
|
||||
maxround(int32 max, int32 v)
|
||||
{
|
||||
v = xround(v, SZ_LONG);
|
||||
if(v > max)
|
||||
return v;
|
||||
return max;
|
||||
}
|
1361
src/cmd/5c/txt.c
1361
src/cmd/5c/txt.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../Make.dist
|
2046
src/cmd/6c/cgen.c
2046
src/cmd/6c/cgen.c
File diff suppressed because it is too large
Load Diff
236
src/cmd/6c/div.c
236
src/cmd/6c/div.c
@ -1,236 +0,0 @@
|
||||
// Inferno utils/6c/div.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/div.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 "gc.h"
|
||||
|
||||
/*
|
||||
* Based on: Granlund, T.; Montgomery, P.L.
|
||||
* "Division by Invariant Integers using Multiplication".
|
||||
* SIGPLAN Notices, Vol. 29, June 1994, page 61.
|
||||
*/
|
||||
|
||||
#define TN(n) ((uvlong)1 << (n))
|
||||
#define T31 TN(31)
|
||||
#define T32 TN(32)
|
||||
|
||||
int
|
||||
multiplier(uint32 d, int p, uvlong *mp)
|
||||
{
|
||||
int l;
|
||||
uvlong mlo, mhi, tlo, thi;
|
||||
|
||||
l = topbit(d - 1) + 1;
|
||||
mlo = (((TN(l) - d) << 32) / d) + T32;
|
||||
if(l + p == 64)
|
||||
mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
|
||||
else
|
||||
mhi = (TN(32 + l) + TN(32 + l - p)) / d;
|
||||
/*assert(mlo < mhi);*/
|
||||
while(l > 0) {
|
||||
tlo = mlo >> 1;
|
||||
thi = mhi >> 1;
|
||||
if(tlo == thi)
|
||||
break;
|
||||
mlo = tlo;
|
||||
mhi = thi;
|
||||
l--;
|
||||
}
|
||||
*mp = mhi;
|
||||
return l;
|
||||
}
|
||||
|
||||
int
|
||||
sdiv(uint32 d, uint32 *mp, int *sp)
|
||||
{
|
||||
int s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32 - 1, &m);
|
||||
*mp = m;
|
||||
*sp = s;
|
||||
if(m >= T31)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udiv(uint32 d, uint32 *mp, int *sp, int *pp)
|
||||
{
|
||||
int p, s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32, &m);
|
||||
p = 0;
|
||||
if(m >= T32) {
|
||||
while((d & 1) == 0) {
|
||||
d >>= 1;
|
||||
p++;
|
||||
}
|
||||
s = multiplier(d, 32 - p, &m);
|
||||
}
|
||||
*mp = m;
|
||||
*pp = p;
|
||||
if(m >= T32) {
|
||||
/*assert(p == 0);*/
|
||||
*sp = s - 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
*sp = s;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s;
|
||||
uint32 m;
|
||||
vlong c;
|
||||
|
||||
c = r->vconst;
|
||||
if(c < 0)
|
||||
c = -c;
|
||||
a = sdiv(c, &m, &s);
|
||||
//print("a=%d i=%d s=%d m=%ux\n", a, (long)r->vconst, s, m);
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AIMULL, l, Z);
|
||||
gins(AMOVL, l, ax);
|
||||
if(a)
|
||||
gins(AADDL, ax, dx);
|
||||
gins(ASHRL, nodconst(31), ax);
|
||||
gins(ASARL, nodconst(s), dx);
|
||||
gins(AADDL, ax, dx);
|
||||
if(r->vconst < 0)
|
||||
gins(ANEGL, Z, dx);
|
||||
}
|
||||
|
||||
void
|
||||
udivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s, t;
|
||||
uint32 m;
|
||||
Node nod;
|
||||
|
||||
a = udiv(r->vconst, &m, &s, &t);
|
||||
//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (long)r->vconst, t, s, m);
|
||||
if(t != 0) {
|
||||
gins(AMOVL, l, ax);
|
||||
gins(ASHRL, nodconst(t), ax);
|
||||
gins(AMOVL, nodconst(m), dx);
|
||||
gins(AMULL, dx, Z);
|
||||
}
|
||||
else if(a) {
|
||||
if(l->op != OREGISTER) {
|
||||
regalloc(&nod, l, Z);
|
||||
gins(AMOVL, l, &nod);
|
||||
l = &nod;
|
||||
}
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
gins(AADDL, l, dx);
|
||||
gins(ARCRL, nodconst(1), dx);
|
||||
if(l == &nod)
|
||||
regfree(l);
|
||||
}
|
||||
else {
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
}
|
||||
if(s != 0)
|
||||
gins(ASHRL, nodconst(s), dx);
|
||||
}
|
||||
|
||||
void
|
||||
sext(Node *d, Node *s, Node *l)
|
||||
{
|
||||
if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
|
||||
reg[D_DX]++;
|
||||
gins(ACDQ, Z, Z);
|
||||
}
|
||||
else {
|
||||
regalloc(d, l, Z);
|
||||
gins(AMOVL, s, d);
|
||||
gins(ASARL, nodconst(31), d);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdiv2(int32 c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(v > 0) {
|
||||
if(v > 1) {
|
||||
sext(&nod, n, l);
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
regfree(&nod);
|
||||
}
|
||||
else {
|
||||
gins(ACMPL, n, nodconst(0x80000000));
|
||||
gins(ASBBL, nodconst(-1), n);
|
||||
}
|
||||
gins(ASARL, nodconst(v), n);
|
||||
}
|
||||
if(c < 0)
|
||||
gins(ANEGL, Z, n);
|
||||
}
|
||||
|
||||
void
|
||||
smod2(int32 c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(c == 1) {
|
||||
zeroregm(n);
|
||||
return;
|
||||
}
|
||||
|
||||
sext(&nod, n, l);
|
||||
if(v == 0) {
|
||||
zeroregm(n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else if(v > 1) {
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
gins(AANDL, nodconst((1 << v) - 1), n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else {
|
||||
gins(AANDL, nodconst(1), n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
regfree(&nod);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
|
||||
6c is a version of the Plan 9 C compiler. The original is documented at
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/1/8c
|
||||
|
||||
Its target architecture is the x86-64, referred to by these tools as amd64.
|
||||
|
||||
*/
|
||||
package main
|
359
src/cmd/6c/gc.h
359
src/cmd/6c/gc.h
@ -1,359 +0,0 @@
|
||||
// Inferno utils/6c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
|
||||
//
|
||||
// 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 "../cc/cc.h"
|
||||
#include "../6l/6.out.h"
|
||||
|
||||
/*
|
||||
* 6c/amd64
|
||||
* Intel 386 with AMD64 extensions
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 8
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
typedef struct Renv Renv;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Node* regtree;
|
||||
Node* basetree;
|
||||
short scale;
|
||||
short reg;
|
||||
short ptr;
|
||||
} idx;
|
||||
|
||||
#define INDEXED 9
|
||||
|
||||
#define A ((Addr*)0)
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
vlong val;
|
||||
int32 label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
vlong val;
|
||||
int32 label;
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
int32 pc;
|
||||
int32 rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu;
|
||||
int32 loop; /* could be shorter */
|
||||
|
||||
Reg* log5;
|
||||
int32 active;
|
||||
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
struct Renv
|
||||
{
|
||||
int safe;
|
||||
Node base;
|
||||
Node* saved;
|
||||
Node* scope;
|
||||
};
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 breakpc;
|
||||
EXTERN int32 nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN Node vconstnode;
|
||||
EXTERN int32 continpc;
|
||||
EXTERN int32 curarg;
|
||||
EXTERN int32 cursafe;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN int32 maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN int32 nrathole;
|
||||
EXTERN int32 nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN int32 pc;
|
||||
EXTERN Node lregnode;
|
||||
EXTERN Node qregnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN int32 exregoffset;
|
||||
EXTERN int32 exfregoffset;
|
||||
EXTERN uchar typechlpv[NTYPE];
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN int32* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN int32 maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void noretval(int);
|
||||
void usedset(Node*, int);
|
||||
void xcom(Node*);
|
||||
void indx(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
Prog* gtext(Sym*, int32);
|
||||
vlong argsize(int);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void zeroregm(Node*);
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, int32);
|
||||
int needreg(Node*, int);
|
||||
int hardconst(Node*);
|
||||
int immconst(Node*);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(int32);
|
||||
Node* nodfconst(double);
|
||||
Node* nodgconst(vlong, Type*);
|
||||
int nodreg(Node*, Node*, int);
|
||||
int isreg(Node*, int);
|
||||
void regret(Node*, Node*, Type*, int);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void naddr(Node*, Addr*);
|
||||
void gcmp(int, Node*, vlong);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Type*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, int32);
|
||||
int sconst(Node*);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
void gprefetch(Node*);
|
||||
void gpcdata(int, int);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, int32, Node*);
|
||||
void swit2(C1*, int, int32, Node*);
|
||||
void newcase(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
int32 outstring(char*, int32);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, int32, int32);
|
||||
void gextern(Sym*, Node*, int32, int32);
|
||||
void outcode(void);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Addr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void addreg(Addr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Addr*);
|
||||
int anyvar(Addr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Addr*, Addr*, Reg*, int);
|
||||
int copyu(Prog*, Addr*, Addr*);
|
||||
|
||||
int copyas(Addr*, Addr*);
|
||||
int copyau(Addr*, Addr*);
|
||||
int copysub(Addr*, Addr*, Addr*, int);
|
||||
int copysub1(Prog*, Addr*, Addr*, int);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
|
||||
#define D_HI D_NONE
|
||||
#define D_LO D_NONE
|
||||
|
||||
/*
|
||||
* bound
|
||||
*/
|
||||
void comtarg(void);
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int cond(int);
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
int32 lo64v(Node*);
|
||||
int32 hi64v(Node*);
|
||||
Node* lo64(Node*);
|
||||
Node* hi64(Node*);
|
||||
|
||||
/*
|
||||
* div/mul
|
||||
*/
|
||||
void sdivgen(Node*, Node*, Node*, Node*);
|
||||
void udivgen(Node*, Node*, Node*, Node*);
|
||||
void sdiv2(int32, int, Node*, Node*);
|
||||
void smod2(int32, int, Node*, Node*);
|
||||
void mulgen(Type*, Node*, Node*);
|
||||
void genmuladd(Node*, Node*, int, Node*);
|
||||
void shiftit(Type*, Node*, Node*);
|
||||
|
||||
#define D_X7 (D_X0+7)
|
||||
|
||||
void fgopcode(int, Node*, Node*, int, int);
|
@ -1,38 +0,0 @@
|
||||
// Inferno utils/6c/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.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.
|
||||
|
||||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
listinit6();
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
// Inferno utils/6c/machcap.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/machcap.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 "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
|
||||
if(n == Z)
|
||||
return 1; /* test */
|
||||
|
||||
switch(n->op) {
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
if(typechl[n->type->etype])
|
||||
return 1;
|
||||
if(typev[n->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
case OASHL:
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
if(typechlv[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
return 1;
|
||||
|
||||
case OCOND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
return 1;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
return 1;
|
||||
|
||||
case OPOSTINC:
|
||||
case OPOSTDEC:
|
||||
case OPREINC:
|
||||
case OPREDEC:
|
||||
return 1;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OGT:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
458
src/cmd/6c/mul.c
458
src/cmd/6c/mul.c
@ -1,458 +0,0 @@
|
||||
// Inferno utils/6c/mul.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/mul.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 "gc.h"
|
||||
|
||||
typedef struct Malg Malg;
|
||||
typedef struct Mparam Mparam;
|
||||
|
||||
struct Malg
|
||||
{
|
||||
schar vals[10];
|
||||
};
|
||||
|
||||
struct Mparam
|
||||
{
|
||||
uint32 value;
|
||||
schar alg;
|
||||
char neg;
|
||||
char shift;
|
||||
char arg;
|
||||
schar off;
|
||||
};
|
||||
|
||||
static Mparam multab[32];
|
||||
static int mulptr;
|
||||
|
||||
static Malg malgs[] =
|
||||
{
|
||||
{0, 100},
|
||||
{-1, 1, 100},
|
||||
{-9, -5, -3, 3, 5, 9, 100},
|
||||
{6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
|
||||
{-8, -4, -2, 2, 4, 8, 100},
|
||||
};
|
||||
|
||||
/*
|
||||
* return position of lowest 1
|
||||
*/
|
||||
int
|
||||
lowbit(uint32 v)
|
||||
{
|
||||
int s, i;
|
||||
uint32 m;
|
||||
|
||||
s = 0;
|
||||
m = 0xFFFFFFFFUL;
|
||||
for(i = 16; i > 0; i >>= 1) {
|
||||
m >>= i;
|
||||
if((v & m) == 0) {
|
||||
v >>= i;
|
||||
s += i;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
genmuladd(Node *d, Node *s, int m, Node *a)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
nod.op = OINDEX;
|
||||
nod.left = a;
|
||||
nod.right = s;
|
||||
nod.scale = m;
|
||||
nod.type = types[TIND];
|
||||
nod.xoffset = 0;
|
||||
xcom(&nod);
|
||||
gopcode(OADDR, d->type, &nod, d);
|
||||
}
|
||||
|
||||
void
|
||||
mulparam(uint32 m, Mparam *mp)
|
||||
{
|
||||
int c, i, j, n, o, q, s;
|
||||
int bc, bi, bn, bo, bq, bs, bt;
|
||||
schar *p;
|
||||
int32 u;
|
||||
uint32 t;
|
||||
|
||||
bc = bq = 10;
|
||||
bi = bn = bo = bs = bt = 0;
|
||||
for(i = 0; i < nelem(malgs); i++) {
|
||||
for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
|
||||
for(s = 0; s < 2; s++) {
|
||||
c = 10;
|
||||
q = 10;
|
||||
u = m - o;
|
||||
if(u == 0)
|
||||
continue;
|
||||
if(s) {
|
||||
o = -o;
|
||||
if(o > 0)
|
||||
continue;
|
||||
u = -u;
|
||||
}
|
||||
n = lowbit(u);
|
||||
t = (uint32)u >> n;
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(t == 1) {
|
||||
c = s + 1;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = s + 1;
|
||||
if(n)
|
||||
c++;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
if(s)
|
||||
break;
|
||||
switch(t) {
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
c = 2;
|
||||
if(n)
|
||||
c++;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 3;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(s)
|
||||
break;
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(c < bc || (c == bc && q > bq)) {
|
||||
bc = c;
|
||||
bi = i;
|
||||
bn = n;
|
||||
bo = o;
|
||||
bq = q;
|
||||
bs = s;
|
||||
bt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp->value = m;
|
||||
if(bc <= 3) {
|
||||
mp->alg = bi;
|
||||
mp->shift = bn;
|
||||
mp->off = bo;
|
||||
mp->neg = bs;
|
||||
mp->arg = bt;
|
||||
}
|
||||
else
|
||||
mp->alg = -1;
|
||||
}
|
||||
|
||||
int
|
||||
m0(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case -2:
|
||||
case 2:
|
||||
return 2;
|
||||
case -3:
|
||||
case 3:
|
||||
return 2;
|
||||
case -4:
|
||||
case 4:
|
||||
return 4;
|
||||
case -5:
|
||||
case 5:
|
||||
return 4;
|
||||
case 6:
|
||||
return 2;
|
||||
case -8:
|
||||
case 8:
|
||||
return 8;
|
||||
case -9:
|
||||
case 9:
|
||||
return 8;
|
||||
case 10:
|
||||
return 4;
|
||||
case 12:
|
||||
return 2;
|
||||
case 15:
|
||||
return 2;
|
||||
case 18:
|
||||
return 8;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 2;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 2;
|
||||
case 36:
|
||||
return 8;
|
||||
case 40:
|
||||
return 4;
|
||||
case 45:
|
||||
return 4;
|
||||
case 72:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m1(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 15:
|
||||
return 4;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 8;
|
||||
case 45:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m2(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 6:
|
||||
return 2;
|
||||
case 10:
|
||||
return 2;
|
||||
case 12:
|
||||
return 4;
|
||||
case 18:
|
||||
return 2;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 8;
|
||||
case 36:
|
||||
return 4;
|
||||
case 40:
|
||||
return 8;
|
||||
case 72:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shiftit(Type *t, Node *s, Node *d)
|
||||
{
|
||||
int32 c;
|
||||
|
||||
c = (int32)s->vconst & 31;
|
||||
switch(c) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
gopcode(OADD, t, d, d);
|
||||
break;
|
||||
default:
|
||||
gopcode(OASHL, t, s, d);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mulgen1(uint32 v, Node *n)
|
||||
{
|
||||
int i, o;
|
||||
Mparam *p;
|
||||
Node nod, nods;
|
||||
|
||||
for(i = 0; i < nelem(multab); i++) {
|
||||
p = &multab[i];
|
||||
if(p->value == v)
|
||||
goto found;
|
||||
}
|
||||
|
||||
p = &multab[mulptr];
|
||||
if(++mulptr == nelem(multab))
|
||||
mulptr = 0;
|
||||
|
||||
mulparam(v, p);
|
||||
|
||||
found:
|
||||
// print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
|
||||
if(p->alg < 0)
|
||||
return 0;
|
||||
|
||||
nods = *nodconst(p->shift);
|
||||
|
||||
o = OADD;
|
||||
if(p->alg > 0) {
|
||||
regalloc(&nod, n, Z);
|
||||
if(p->off < 0)
|
||||
o = OSUB;
|
||||
}
|
||||
|
||||
switch(p->alg) {
|
||||
case 0:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
genmuladd(n, n, m1(p->arg), n);
|
||||
/* fall thru */
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(n, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg == 1)
|
||||
gins(ANEGL, Z, n);
|
||||
break;
|
||||
case 1:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
gmove(n, &nod);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(&nod, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg)
|
||||
gopcode(o, n->type, &nod, n);
|
||||
else {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
case 3:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
genmuladd(n, &nod, m2(p->off), n);
|
||||
break;
|
||||
case 4:
|
||||
genmuladd(&nod, n, m0(p->off), nodconst(0));
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
default:
|
||||
diag(Z, "bad mul alg");
|
||||
break;
|
||||
comop:
|
||||
if(p->neg) {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
else
|
||||
gopcode(o, n->type, &nod, n);
|
||||
}
|
||||
|
||||
if(p->alg > 0)
|
||||
regfree(&nod);
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
diag(Z, "mulgen botch");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mulgen(Type *t, Node *r, Node *n)
|
||||
{
|
||||
if(!mulgen1(r->vconst, n))
|
||||
gopcode(OMUL, t, r, n);
|
||||
}
|
@ -1,902 +0,0 @@
|
||||
// Inferno utils/6c/peep.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.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 "gc.h"
|
||||
|
||||
static int
|
||||
needc(Prog *p)
|
||||
{
|
||||
while(p != P) {
|
||||
switch(p->as) {
|
||||
case AADCL:
|
||||
case AADCQ:
|
||||
case ASBBL:
|
||||
case ASBBQ:
|
||||
case ARCRL:
|
||||
case ARCRQ:
|
||||
return 1;
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case ACALL:
|
||||
return 0;
|
||||
default:
|
||||
if(p->to.type == D_BRANCH)
|
||||
return 0;
|
||||
}
|
||||
p = p->link;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Reg*
|
||||
rnops(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
Reg *r1;
|
||||
|
||||
if(r != R)
|
||||
for(;;){
|
||||
p = r->prog;
|
||||
if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
|
||||
break;
|
||||
r1 = uniqs(r);
|
||||
if(r1 == R)
|
||||
break;
|
||||
r = r1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
peep(void)
|
||||
{
|
||||
Reg *r, *r1, *r2;
|
||||
Prog *p, *p1;
|
||||
int t;
|
||||
|
||||
/*
|
||||
* complete R structure
|
||||
*/
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r1) {
|
||||
r1 = r->link;
|
||||
if(r1 == R)
|
||||
break;
|
||||
p = r->prog->link;
|
||||
while(p != r1->prog)
|
||||
switch(p->as) {
|
||||
default:
|
||||
r2 = rega();
|
||||
r->link = r2;
|
||||
r2->link = r1;
|
||||
|
||||
r2->prog = p;
|
||||
r2->p1 = r;
|
||||
r->s1 = r2;
|
||||
r2->s1 = r1;
|
||||
r1->p1 = r2;
|
||||
|
||||
r = r2;
|
||||
t++;
|
||||
|
||||
case ADATA:
|
||||
case AGLOBL:
|
||||
case ANAME:
|
||||
case ASIGNAME:
|
||||
p = p->link;
|
||||
}
|
||||
}
|
||||
|
||||
pc = 0; /* speculating it won't kill */
|
||||
|
||||
loop1:
|
||||
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
if(regtyp(&p->to))
|
||||
if(regtyp(&p->from)) {
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
} else
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBLZX:
|
||||
case AMOVWLZX:
|
||||
case AMOVBLSX:
|
||||
case AMOVWLSX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVL;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVQ;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1) {
|
||||
if(p->as == ASUBQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == ASUBQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(t)
|
||||
goto loop1;
|
||||
}
|
||||
|
||||
void
|
||||
excise(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = r->prog;
|
||||
p->as = ANOP;
|
||||
p->from = zprog.from;
|
||||
p->to = zprog.to;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqp(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->p1;
|
||||
if(r1 == R) {
|
||||
r1 = r->p2;
|
||||
if(r1 == R || r1->p2link != R)
|
||||
return R;
|
||||
} else
|
||||
if(r->p2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqs(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->s1;
|
||||
if(r1 == R) {
|
||||
r1 = r->s2;
|
||||
if(r1 == R)
|
||||
return R;
|
||||
} else
|
||||
if(r->s2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
int
|
||||
regtyp(Addr *a)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = a->type;
|
||||
if(t >= D_AX && t <= D_R15)
|
||||
return 1;
|
||||
if(t >= D_X0 && t <= D_X0+15)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the idea is to substitute
|
||||
* one register for another
|
||||
* from one MOV to another
|
||||
* MOV a, R0
|
||||
* ADD b, R0 / no use of R1
|
||||
* MOV R0, R1
|
||||
* would be converted to
|
||||
* MOV a, R1
|
||||
* ADD b, R1
|
||||
* MOV R1, R0
|
||||
* hopefully, then the former or latter MOV
|
||||
* will be eliminated by copy propagation.
|
||||
*/
|
||||
int
|
||||
subprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Addr *v1, *v2;
|
||||
Reg *r;
|
||||
int t;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
if(!regtyp(v1))
|
||||
return 0;
|
||||
v2 = &p->to;
|
||||
if(!regtyp(v2))
|
||||
return 0;
|
||||
for(r=uniqp(r0); r!=R; r=uniqp(r)) {
|
||||
if(uniqs(r) == R)
|
||||
break;
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case ACALL:
|
||||
return 0;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE)
|
||||
break;
|
||||
goto giveup;
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
if(p->from.type == D_CONST)
|
||||
break;
|
||||
goto giveup;
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
case ASTOSQ:
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
case AMOVQL:
|
||||
giveup:
|
||||
return 0;
|
||||
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
if(p->to.type == v1->type)
|
||||
goto gotit;
|
||||
break;
|
||||
}
|
||||
if(copyau(&p->from, v2) ||
|
||||
copyau(&p->to, v2))
|
||||
break;
|
||||
if(copysub(&p->from, v1, v2, 0) ||
|
||||
copysub(&p->to, v1, v2, 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
gotit:
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P']) {
|
||||
print("gotit: %D->%D\n%P", v1, v2, r->prog);
|
||||
if(p->from.type == v2->type)
|
||||
print(" excise");
|
||||
print("\n");
|
||||
}
|
||||
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
|
||||
p = r->prog;
|
||||
copysub(&p->from, v1, v2, 1);
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P'])
|
||||
print("%P\n", r->prog);
|
||||
}
|
||||
t = v1->type;
|
||||
v1->type = v2->type;
|
||||
v2->type = t;
|
||||
if(debug['P'])
|
||||
print("%P last\n", r->prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idea is to remove redundant copies.
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* use v2 return fail
|
||||
* -----------------
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* set v2 return success
|
||||
*/
|
||||
int
|
||||
copyprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Addr *v1, *v2;
|
||||
Reg *r;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
v2 = &p->to;
|
||||
if(copyas(v1, v2))
|
||||
return 1;
|
||||
for(r=firstr; r!=R; r=r->link)
|
||||
r->active = 0;
|
||||
return copy1(v1, v2, r0->s1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
copy1(Addr *v1, Addr *v2, Reg *r, int f)
|
||||
{
|
||||
int t;
|
||||
Prog *p;
|
||||
|
||||
if(r->active) {
|
||||
if(debug['P'])
|
||||
print("act set; return 1\n");
|
||||
return 1;
|
||||
}
|
||||
r->active = 1;
|
||||
if(debug['P'])
|
||||
print("copy %D->%D f=%d\n", v1, v2, f);
|
||||
for(; r != R; r = r->s1) {
|
||||
p = r->prog;
|
||||
if(debug['P'])
|
||||
print("%P", p);
|
||||
if(!f && uniqp(r) == R) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; merge; f=%d", f);
|
||||
}
|
||||
t = copyu(p, v2, A);
|
||||
switch(t) {
|
||||
case 2: /* rar, can't split */
|
||||
if(debug['P'])
|
||||
print("; %D rar; return 0\n", v2);
|
||||
return 0;
|
||||
|
||||
case 3: /* set */
|
||||
if(debug['P'])
|
||||
print("; %D set; return 1\n", v2);
|
||||
return 1;
|
||||
|
||||
case 1: /* used, substitute */
|
||||
case 4: /* use and set */
|
||||
if(f) {
|
||||
if(!debug['P'])
|
||||
return 0;
|
||||
if(t == 4)
|
||||
print("; %D used+set and f=%d; return 0\n", v2, f);
|
||||
else
|
||||
print("; %D used and f=%d; return 0\n", v2, f);
|
||||
return 0;
|
||||
}
|
||||
if(copyu(p, v2, v1)) {
|
||||
if(debug['P'])
|
||||
print("; sub fail; return 0\n");
|
||||
return 0;
|
||||
}
|
||||
if(debug['P'])
|
||||
print("; sub %D/%D", v2, v1);
|
||||
if(t == 4) {
|
||||
if(debug['P'])
|
||||
print("; %D used+set; return 1\n", v2);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!f) {
|
||||
t = copyu(p, v1, A);
|
||||
if(!f && (t == 2 || t == 3 || t == 4)) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; %D set and !f; f=%d", v1, f);
|
||||
}
|
||||
}
|
||||
if(debug['P'])
|
||||
print("\n");
|
||||
if(r->s2)
|
||||
if(!copy1(v1, v2, r->s2, f))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return
|
||||
* 1 if v only used (and substitute),
|
||||
* 2 if read-alter-rewrite
|
||||
* 3 if set
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
copyu(Prog *p, Addr *v, Addr *s)
|
||||
{
|
||||
|
||||
switch(p->as) {
|
||||
|
||||
default:
|
||||
if(debug['P'])
|
||||
print("unknown op %A\n", p->as);
|
||||
/* SBBL; ADCL; FLD1; SAHF */
|
||||
return 2;
|
||||
|
||||
|
||||
case ANEGB:
|
||||
case ANEGW:
|
||||
case ANEGL:
|
||||
case ANEGQ:
|
||||
case ANOTB:
|
||||
case ANOTW:
|
||||
case ANOTL:
|
||||
case ANOTQ:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ALEAL: /* lhs addr, rhs store */
|
||||
case ALEAQ:
|
||||
if(copyas(&p->from, v))
|
||||
return 2;
|
||||
|
||||
|
||||
case ANOP: /* rhs store */
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVBLSX:
|
||||
case AMOVBLZX:
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
case AMOVWLSX:
|
||||
case AMOVWLZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
case AMOVQL:
|
||||
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
case ACVTSD2SL:
|
||||
case ACVTSD2SQ:
|
||||
case ACVTSD2SS:
|
||||
case ACVTSL2SD:
|
||||
case ACVTSL2SS:
|
||||
case ACVTSQ2SD:
|
||||
case ACVTSQ2SS:
|
||||
case ACVTSS2SD:
|
||||
case ACVTSS2SL:
|
||||
case ACVTSS2SQ:
|
||||
case ACVTTSD2SL:
|
||||
case ACVTTSD2SQ:
|
||||
case ACVTTSS2SL:
|
||||
case ACVTTSS2SQ:
|
||||
if(copyas(&p->to, v)) {
|
||||
if(s != A)
|
||||
return copysub(&p->from, v, s, 1);
|
||||
if(copyau(&p->from, v))
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
goto caseread;
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
if(copyas(&p->from, v))
|
||||
if(p->from.type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AADDB: /* rhs rar */
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
case AANDB:
|
||||
case AANDL:
|
||||
case AANDQ:
|
||||
case AANDW:
|
||||
case ADECL:
|
||||
case ADECQ:
|
||||
case ADECW:
|
||||
case AINCL:
|
||||
case AINCQ:
|
||||
case AINCW:
|
||||
case ASUBB:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
case AORB:
|
||||
case AORL:
|
||||
case AORQ:
|
||||
case AORW:
|
||||
case AXORB:
|
||||
case AXORL:
|
||||
case AXORQ:
|
||||
case AXORW:
|
||||
case AMOVB:
|
||||
case AMOVW:
|
||||
|
||||
case AADDSD:
|
||||
case AADDSS:
|
||||
case ACMPSD:
|
||||
case ACMPSS:
|
||||
case ADIVSD:
|
||||
case ADIVSS:
|
||||
case AMAXSD:
|
||||
case AMAXSS:
|
||||
case AMINSD:
|
||||
case AMINSS:
|
||||
case AMULSD:
|
||||
case AMULSS:
|
||||
case ARCPSS:
|
||||
case ARSQRTSS:
|
||||
case ASQRTSD:
|
||||
case ASQRTSS:
|
||||
case ASUBSD:
|
||||
case ASUBSS:
|
||||
case AXORPD:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ACMPL: /* read only */
|
||||
case ACMPW:
|
||||
case ACMPB:
|
||||
case ACMPQ:
|
||||
|
||||
case APREFETCHT0:
|
||||
case APREFETCHT1:
|
||||
case APREFETCHT2:
|
||||
case APREFETCHNTA:
|
||||
|
||||
case ACOMISD:
|
||||
case ACOMISS:
|
||||
case AUCOMISD:
|
||||
case AUCOMISS:
|
||||
caseread:
|
||||
if(s != A) {
|
||||
if(copysub(&p->from, v, s, 1))
|
||||
return 1;
|
||||
return copysub(&p->to, v, s, 1);
|
||||
}
|
||||
if(copyau(&p->from, v))
|
||||
return 1;
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case AJGE: /* no reference */
|
||||
case AJNE:
|
||||
case AJLE:
|
||||
case AJEQ:
|
||||
case AJHI:
|
||||
case AJLS:
|
||||
case AJMI:
|
||||
case AJPL:
|
||||
case AJGT:
|
||||
case AJLT:
|
||||
case AJCC:
|
||||
case AJCS:
|
||||
|
||||
case AADJSP:
|
||||
case AWAIT:
|
||||
case ACLD:
|
||||
break;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE) {
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
}
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
if(v->type == D_AX || v->type == D_DX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
if(v->type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
if(v->type == D_DI || v->type == D_SI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
case ASTOSQ:
|
||||
if(v->type == D_AX || v->type == D_DI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AJMP: /* funny */
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case ARET: /* funny */
|
||||
if(v->type == REGRET || v->type == FREGRET)
|
||||
return 2;
|
||||
if(s != A)
|
||||
return 1;
|
||||
return 3;
|
||||
|
||||
case ACALL: /* funny */
|
||||
if(REGARG >= 0 && v->type == (uchar)REGARG)
|
||||
return 2;
|
||||
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 4;
|
||||
return 3;
|
||||
|
||||
case ATEXT: /* funny */
|
||||
if(REGARG >= 0 && v->type == (uchar)REGARG)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* direct reference,
|
||||
* could be set/use depending on
|
||||
* semantics
|
||||
*/
|
||||
int
|
||||
copyas(Addr *a, Addr *v)
|
||||
{
|
||||
if(a->type != v->type)
|
||||
return 0;
|
||||
if(regtyp(v))
|
||||
return 1;
|
||||
if(v->type == D_AUTO || v->type == D_PARAM)
|
||||
if(v->offset == a->offset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* either direct or indirect
|
||||
*/
|
||||
int
|
||||
copyau(Addr *a, Addr *v)
|
||||
{
|
||||
|
||||
if(copyas(a, v))
|
||||
return 1;
|
||||
if(regtyp(v)) {
|
||||
if(a->type-D_INDIR == v->type)
|
||||
return 1;
|
||||
if(a->index == v->type)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* substitute s for v in a
|
||||
* return failure to substitute
|
||||
*/
|
||||
int
|
||||
copysub(Addr *a, Addr *v, Addr *s, int f)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(copyas(a, v)) {
|
||||
t = s->type;
|
||||
if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
|
||||
if(f)
|
||||
a->type = t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(regtyp(v)) {
|
||||
t = v->type;
|
||||
if(a->type == t+D_INDIR) {
|
||||
if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
|
||||
return 1; /* can't use BP-base with index */
|
||||
if(f)
|
||||
a->type = s->type+D_INDIR;
|
||||
// return 0;
|
||||
}
|
||||
if(a->index == t) {
|
||||
if(f)
|
||||
a->index = s->type;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
1523
src/cmd/6c/reg.c
1523
src/cmd/6c/reg.c
File diff suppressed because it is too large
Load Diff
@ -1,483 +0,0 @@
|
||||
// Inferno utils/6c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.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 "gc.h"
|
||||
#include "../../runtime/funcdata.h"
|
||||
|
||||
Prog*
|
||||
gtext(Sym *s, int32 stkoff)
|
||||
{
|
||||
vlong v;
|
||||
|
||||
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
|
||||
if((textflag & NOSPLIT) && stkoff >= 128)
|
||||
yyerror("stack frame too large for NOSPLIT function");
|
||||
|
||||
gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome to commute */
|
||||
static void
|
||||
commute(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(r->complex > l->complex) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indexshift(Node *n)
|
||||
{
|
||||
int g;
|
||||
|
||||
if(!typechlpv[n->type->etype])
|
||||
return;
|
||||
simplifyshift(n);
|
||||
if(n->op == OASHL && n->right->op == OCONST){
|
||||
g = vconst(n->right);
|
||||
if(g >= 0 && g <= 3)
|
||||
n->addable = 7;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* NAME ==> 10/11 name+value(SB/SP)
|
||||
* REGISTER ==> 12 register
|
||||
* CONST ==> 20 $value
|
||||
* *(20) ==> 21 value
|
||||
* &(10) ==> 13 $name+value(SB)
|
||||
* &(11) ==> 1 $name+value(SP)
|
||||
* (13) + (20) ==> 13 fold constants
|
||||
* (1) + (20) ==> 1 fold constants
|
||||
* *(13) ==> 10 back to name
|
||||
* *(1) ==> 11 back to name
|
||||
*
|
||||
* (20) * (X) ==> 7 multiplier in indexing
|
||||
* (X,7) + (13,1) ==> 8 adder in indexing (addresses)
|
||||
* (8) ==> &9(OINDEX) index, almost addressable
|
||||
*
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int g;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->complex = 0;
|
||||
n->addable = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 9;
|
||||
if(n->class == CPARAM || n->class == CAUTO)
|
||||
n->addable = 11;
|
||||
break;
|
||||
|
||||
case OEXREG:
|
||||
n->addable = 0;
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 13;
|
||||
else
|
||||
if(l->addable == 11)
|
||||
n->addable = 1;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(n->type->etype != TIND)
|
||||
break;
|
||||
|
||||
switch(r->addable) {
|
||||
case 20:
|
||||
switch(l->addable) {
|
||||
case 1:
|
||||
case 13:
|
||||
commadd:
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
l = new(0, Z, Z);
|
||||
*l = *(n->left);
|
||||
l->xoffset += r->vconst;
|
||||
n->left = l;
|
||||
r = n->right;
|
||||
goto brk;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 13:
|
||||
case 10:
|
||||
case 11:
|
||||
/* l is the base, r is the index */
|
||||
if(l->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
switch(r->addable) {
|
||||
case 13:
|
||||
case 1:
|
||||
r = n->left;
|
||||
l = n->right;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
goto commadd;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
case 1:
|
||||
case 10:
|
||||
case 11:
|
||||
/* r is the base, l is the index */
|
||||
if(r->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
if(n->addable == 8 && !side(n) && !nacl) {
|
||||
indx(n);
|
||||
l = new1(OINDEX, idx.basetree, idx.regtree);
|
||||
l->scale = idx.scale;
|
||||
l->addable = 9;
|
||||
l->complex = l->right->complex;
|
||||
l->type = l->left->type;
|
||||
n->op = OADDR;
|
||||
n->left = l;
|
||||
n->right = Z;
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OINDEX:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
n->addable = 9;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->op == OADDR) {
|
||||
l = l->left;
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
return;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
n->addable = 21;
|
||||
break;
|
||||
case 1:
|
||||
n->addable = 11;
|
||||
break;
|
||||
case 13:
|
||||
n->addable = 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(l);
|
||||
if(g >= 0) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
commute(n);
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = g;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
brk:
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(l->type->etype == TUVLONG && typefd[n->type->etype])
|
||||
n->complex += 2;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
case OMOD:
|
||||
case OLMUL:
|
||||
case OLDIV:
|
||||
case OMUL:
|
||||
case ODIV:
|
||||
case OASLMUL:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASMUL:
|
||||
case OASDIV:
|
||||
case OASMOD:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 3;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 3;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case OASLSHR:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 2;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 2;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
/*
|
||||
* compare operators, make const on left
|
||||
*/
|
||||
if(r->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
n->op = invrel[relindex(n->op)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indx(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(debug['x'])
|
||||
prtree(n, "indx");
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
|
||||
n->right = l;
|
||||
n->left = r;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
if(l->addable != 7) {
|
||||
idx.regtree = l;
|
||||
idx.scale = 1;
|
||||
} else
|
||||
if(l->right->addable == 20) {
|
||||
idx.regtree = l->left;
|
||||
idx.scale = 1 << l->right->vconst;
|
||||
} else
|
||||
if(l->left->addable == 20) {
|
||||
idx.regtree = l->right;
|
||||
idx.scale = 1 << l->left->vconst;
|
||||
} else
|
||||
diag(n, "bad index");
|
||||
|
||||
idx.basetree = r;
|
||||
if(debug['x']) {
|
||||
print("scale = %d\n", idx.scale);
|
||||
prtree(idx.regtree, "index");
|
||||
prtree(idx.basetree, "base");
|
||||
}
|
||||
}
|
353
src/cmd/6c/swt.c
353
src/cmd/6c/swt.c
@ -1,353 +0,0 @@
|
||||
// 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 "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
Node nreg;
|
||||
|
||||
regalloc(&nreg, n, Z);
|
||||
if(typev[n->type->etype])
|
||||
nreg.type = types[TVLONG];
|
||||
else
|
||||
nreg.type = types[TLONG];
|
||||
cgen(n, &nreg);
|
||||
swit2(q, nc, def, &nreg);
|
||||
regfree(&nreg);
|
||||
}
|
||||
|
||||
void
|
||||
swit2(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
Prog *sp;
|
||||
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8llux\n", q->val);
|
||||
gcmp(OEQ, n, q->val);
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8llux\n", r->val);
|
||||
gcmp(OGT, n, r->val);
|
||||
sp = p;
|
||||
gbranch(OGOTO);
|
||||
p->as = AJEQ;
|
||||
patch(p, r->label);
|
||||
swit2(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
int32 v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gmove(n2, n3);
|
||||
gmove(n3, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, tfield, nodconst(v), n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, tfield, nodconst(sh), n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, tfield, nodconst(sh), n1);
|
||||
else
|
||||
gopcode(OASHR, tfield, nodconst(sh), n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int32 v;
|
||||
Node nod;
|
||||
int sh;
|
||||
|
||||
regalloc(&nod, b->left, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, types[TLONG], nodconst(v), n1);
|
||||
gmove(n1, &nod);
|
||||
if(nn != Z)
|
||||
gmove(n1, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, types[TLONG], nodconst(~v), n3);
|
||||
gopcode(OOR, types[TLONG], n3, &nod);
|
||||
gmove(&nod, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
int32
|
||||
outstring(char *s, int32 n)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->from.scale = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
int32 e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0L));
|
||||
p->from.offset += o+e;
|
||||
p->from.scale = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
if(0 && a->op == OCONST && typev[a->type->etype]) {
|
||||
gpseudo(ADATA, s, lo64(a));
|
||||
p->from.offset += o;
|
||||
p->from.scale = 4;
|
||||
gpseudo(ADATA, s, hi64(a));
|
||||
p->from.offset += o + 4;
|
||||
p->from.scale = 4;
|
||||
return;
|
||||
}
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->from.scale = w;
|
||||
switch(p->to.type) {
|
||||
default:
|
||||
p->to.index = p->to.type;
|
||||
p->to.type = D_ADDR;
|
||||
case D_CONST:
|
||||
case D_FCONST:
|
||||
case D_ADDR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
int f;
|
||||
Biobuf b;
|
||||
|
||||
f = open(outfile, OWRITE);
|
||||
if(f < 0) {
|
||||
diag(Z, "cannot open %s", outfile);
|
||||
return;
|
||||
}
|
||||
Binit(&b, f, OWRITE);
|
||||
|
||||
Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
|
||||
if(pragcgobuf.to > pragcgobuf.start) {
|
||||
Bprint(&b, "\n");
|
||||
Bprint(&b, "$$ // exports\n\n");
|
||||
Bprint(&b, "$$ // local types\n\n");
|
||||
Bprint(&b, "$$ // cgo\n");
|
||||
Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
|
||||
Bprint(&b, "\n$$\n\n");
|
||||
}
|
||||
Bprint(&b, "!\n");
|
||||
|
||||
writeobj(ctxt, &b);
|
||||
Bterm(&b);
|
||||
close(f);
|
||||
lastp = P;
|
||||
}
|
||||
|
||||
int32
|
||||
align(int32 i, Type *t, int op, int32 *maxalign)
|
||||
{
|
||||
int32 o;
|
||||
Type *v;
|
||||
int w, packw;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
packw = 0;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = *maxalign;
|
||||
if(w < 1)
|
||||
w = 1;
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
if(v->etype == TSTRUCT || v->etype == TUNION)
|
||||
w = v->align;
|
||||
else
|
||||
w = ewidth[v->etype];
|
||||
if(w < 1 || w > SZ_VLONG)
|
||||
fatal(Z, "align");
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesu[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1, nil);
|
||||
o = align(o, types[TIND], Aarg2, nil);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
if(ewidth[TIND] == 4) {
|
||||
if(typesu[t->etype]) {
|
||||
for(v = t->link; v != T; v = v->down)
|
||||
o = align(o, v, Aarg1, maxalign);
|
||||
goto out;
|
||||
}
|
||||
w = ewidth[t->etype];
|
||||
if(typev[t->etype] || t->etype == TDOUBLE)
|
||||
w = 8;
|
||||
else if(w <= 0 || w >= 4)
|
||||
w = 4;
|
||||
else
|
||||
w = 1;
|
||||
break;
|
||||
}
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG) {
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
}
|
||||
w = 1; /* little endian no adjustment */
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
if(ewidth[TIND] == 4) {
|
||||
o = align(o, t, Aarg1, maxalign);
|
||||
goto out;
|
||||
}
|
||||
w = t->width;
|
||||
if(w > SZ_VLONG)
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total align of automatic */
|
||||
o = align(o, t, Ael1, nil);
|
||||
o = align(o, t, Ael2, nil);
|
||||
break;
|
||||
}
|
||||
if(packw != 0 && xround(o, w) != xround(o, packw))
|
||||
diag(Z, "#pragma pack changes offset of %T", t);
|
||||
o = xround(o, w);
|
||||
if(maxalign && *maxalign < w)
|
||||
*maxalign = w;
|
||||
out:
|
||||
if(debug['A'])
|
||||
print("align %s %d %T = %d\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int32
|
||||
maxround(int32 max, int32 v)
|
||||
{
|
||||
v = xround(v, SZ_VLONG);
|
||||
if(v > max)
|
||||
return v;
|
||||
return max;
|
||||
}
|
1674
src/cmd/6c/txt.c
1674
src/cmd/6c/txt.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../Make.dist
|
1939
src/cmd/8c/cgen.c
1939
src/cmd/8c/cgen.c
File diff suppressed because it is too large
Load Diff
2657
src/cmd/8c/cgen64.c
2657
src/cmd/8c/cgen64.c
File diff suppressed because it is too large
Load Diff
236
src/cmd/8c/div.c
236
src/cmd/8c/div.c
@ -1,236 +0,0 @@
|
||||
// Inferno utils/8c/div.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/div.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 "gc.h"
|
||||
|
||||
/*
|
||||
* Based on: Granlund, T.; Montgomery, P.L.
|
||||
* "Division by Invariant Integers using Multiplication".
|
||||
* SIGPLAN Notices, Vol. 29, June 1994, page 61.
|
||||
*/
|
||||
|
||||
#define TN(n) ((uvlong)1 << (n))
|
||||
#define T31 TN(31)
|
||||
#define T32 TN(32)
|
||||
|
||||
int
|
||||
multiplier(uint32 d, int p, uvlong *mp)
|
||||
{
|
||||
int l;
|
||||
uvlong mlo, mhi, tlo, thi;
|
||||
|
||||
l = topbit(d - 1) + 1;
|
||||
mlo = (((TN(l) - d) << 32) / d) + T32;
|
||||
if(l + p == 64)
|
||||
mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
|
||||
else
|
||||
mhi = (TN(32 + l) + TN(32 + l - p)) / d;
|
||||
/*assert(mlo < mhi);*/
|
||||
while(l > 0) {
|
||||
tlo = mlo >> 1;
|
||||
thi = mhi >> 1;
|
||||
if(tlo == thi)
|
||||
break;
|
||||
mlo = tlo;
|
||||
mhi = thi;
|
||||
l--;
|
||||
}
|
||||
*mp = mhi;
|
||||
return l;
|
||||
}
|
||||
|
||||
int
|
||||
sdiv(uint32 d, uint32 *mp, int *sp)
|
||||
{
|
||||
int s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32 - 1, &m);
|
||||
*mp = m;
|
||||
*sp = s;
|
||||
if(m >= T31)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udiv(uint32 d, uint32 *mp, int *sp, int *pp)
|
||||
{
|
||||
int p, s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32, &m);
|
||||
p = 0;
|
||||
if(m >= T32) {
|
||||
while((d & 1) == 0) {
|
||||
d >>= 1;
|
||||
p++;
|
||||
}
|
||||
s = multiplier(d, 32 - p, &m);
|
||||
}
|
||||
*mp = m;
|
||||
*pp = p;
|
||||
if(m >= T32) {
|
||||
/*assert(p == 0);*/
|
||||
*sp = s - 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
*sp = s;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s;
|
||||
uint32 m;
|
||||
vlong c;
|
||||
|
||||
c = r->vconst;
|
||||
if(c < 0)
|
||||
c = -c;
|
||||
a = sdiv(c, &m, &s);
|
||||
//print("a=%d i=%d s=%d m=%ux\n", a, (int32)r->vconst, s, m);
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AIMULL, l, Z);
|
||||
gins(AMOVL, l, ax);
|
||||
if(a)
|
||||
gins(AADDL, ax, dx);
|
||||
gins(ASHRL, nodconst(31), ax);
|
||||
gins(ASARL, nodconst(s), dx);
|
||||
gins(AADDL, ax, dx);
|
||||
if(r->vconst < 0)
|
||||
gins(ANEGL, Z, dx);
|
||||
}
|
||||
|
||||
void
|
||||
udivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s, t;
|
||||
uint32 m;
|
||||
Node nod;
|
||||
|
||||
a = udiv(r->vconst, &m, &s, &t);
|
||||
//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (int32)r->vconst, t, s, m);
|
||||
if(t != 0) {
|
||||
gins(AMOVL, l, ax);
|
||||
gins(ASHRL, nodconst(t), ax);
|
||||
gins(AMOVL, nodconst(m), dx);
|
||||
gins(AMULL, dx, Z);
|
||||
}
|
||||
else if(a) {
|
||||
if(l->op != OREGISTER) {
|
||||
regalloc(&nod, l, Z);
|
||||
gins(AMOVL, l, &nod);
|
||||
l = &nod;
|
||||
}
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
gins(AADDL, l, dx);
|
||||
gins(ARCRL, nodconst(1), dx);
|
||||
if(l == &nod)
|
||||
regfree(l);
|
||||
}
|
||||
else {
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
}
|
||||
if(s != 0)
|
||||
gins(ASHRL, nodconst(s), dx);
|
||||
}
|
||||
|
||||
void
|
||||
sext(Node *d, Node *s, Node *l)
|
||||
{
|
||||
if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
|
||||
reg[D_DX]++;
|
||||
gins(ACDQ, Z, Z);
|
||||
}
|
||||
else {
|
||||
regalloc(d, l, Z);
|
||||
gins(AMOVL, s, d);
|
||||
gins(ASARL, nodconst(31), d);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdiv2(int32 c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(v > 0) {
|
||||
if(v > 1) {
|
||||
sext(&nod, n, l);
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
regfree(&nod);
|
||||
}
|
||||
else {
|
||||
gins(ACMPL, n, nodconst(0x80000000));
|
||||
gins(ASBBL, nodconst(-1), n);
|
||||
}
|
||||
gins(ASARL, nodconst(v), n);
|
||||
}
|
||||
if(c < 0)
|
||||
gins(ANEGL, Z, n);
|
||||
}
|
||||
|
||||
void
|
||||
smod2(int32 c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(c == 1) {
|
||||
zeroregm(n);
|
||||
return;
|
||||
}
|
||||
|
||||
sext(&nod, n, l);
|
||||
if(v == 0) {
|
||||
zeroregm(n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else if(v > 1) {
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
gins(AANDL, nodconst((1 << v) - 1), n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else {
|
||||
gins(AANDL, nodconst(1), n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
regfree(&nod);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
|
||||
8c is a version of the Plan 9 C compiler. The original is documented at
|
||||
|
||||
http://plan9.bell-labs.com/magic/man2html/1/8c
|
||||
|
||||
Its target architecture is the x86, referred to by these tools for historical reasons as 386.
|
||||
|
||||
*/
|
||||
package main
|
364
src/cmd/8c/gc.h
364
src/cmd/8c/gc.h
@ -1,364 +0,0 @@
|
||||
// Inferno utils/8c/gc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/gc.h
|
||||
//
|
||||
// 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 "../cc/cc.h"
|
||||
#include "../8l/8.out.h"
|
||||
|
||||
/*
|
||||
* 8c/386
|
||||
* Intel 386
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 4
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
typedef struct Renv Renv;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Node* regtree;
|
||||
Node* basetree;
|
||||
short scale;
|
||||
short reg;
|
||||
short ptr;
|
||||
} idx;
|
||||
|
||||
#define A ((Addr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
int32 val;
|
||||
int32 label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
int32 val;
|
||||
int32 label;
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
int32 pc;
|
||||
int32 rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
int32 regu;
|
||||
int32 loop; /* could be shorter */
|
||||
|
||||
Reg* log5;
|
||||
int32 active;
|
||||
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
struct Renv
|
||||
{
|
||||
int safe;
|
||||
Node base;
|
||||
Node* saved;
|
||||
Node* scope;
|
||||
};
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN int32 breakpc;
|
||||
EXTERN int32 nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN int32 continpc;
|
||||
EXTERN int32 curarg;
|
||||
EXTERN int32 cursafe;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN int32 maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN int32 nrathole;
|
||||
EXTERN int32 nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN int32 pc;
|
||||
EXTERN Node regnode;
|
||||
EXTERN Node fregnode0;
|
||||
EXTERN Node fregnode1;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN int32 exregoffset;
|
||||
EXTERN int32 exfregoffset;
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN int32 regbits;
|
||||
EXTERN int32 exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN int32* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN int32 maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void noretval(int);
|
||||
void usedset(Node*, int);
|
||||
void xcom(Node*);
|
||||
void indx(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
Prog* gtext(Sym*, int32);
|
||||
vlong argsize(int);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void zeroregm(Node*);
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, int32);
|
||||
int needreg(Node*, int);
|
||||
|
||||
/*
|
||||
* cgen64.c
|
||||
*/
|
||||
int vaddr(Node*, int);
|
||||
void loadpair(Node*, Node*);
|
||||
int cgen64(Node*, Node*);
|
||||
void testv(Node*, int);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(int32);
|
||||
Node* nodfconst(double);
|
||||
int nodreg(Node*, Node*, int);
|
||||
int isreg(Node*, int);
|
||||
void regret(Node*, Node*, Type*, int);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void naddr(Node*, Addr*);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void fgopcode(int, Node*, Node*, int, int);
|
||||
void gopcode(int, Type*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, int32);
|
||||
int sconst(Node*);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
void gprefetch(Node*);
|
||||
void gpcdata(int, int);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, int32, Node*);
|
||||
void swit2(C1*, int, int32, Node*);
|
||||
void newcase(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
int32 outstring(char*, int32);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, int32, int32);
|
||||
void gextern(Sym*, Node*, int32, int32);
|
||||
void outcode(void);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Addr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
void paint3(Reg*, int, int32, int);
|
||||
void addreg(Addr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Addr*);
|
||||
int anyvar(Addr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Addr*, Addr*, Reg*, int);
|
||||
int copyu(Prog*, Addr*, Addr*);
|
||||
|
||||
int copyas(Addr*, Addr*);
|
||||
int copyau(Addr*, Addr*);
|
||||
int copysub(Addr*, Addr*, Addr*, int);
|
||||
int copysub1(Prog*, Addr*, Addr*, int);
|
||||
|
||||
int32 RtoB(int);
|
||||
int32 FtoB(int);
|
||||
int BtoR(int32);
|
||||
int BtoF(int32);
|
||||
|
||||
#define D_HI D_NONE
|
||||
#define D_LO D_NONE
|
||||
|
||||
/*
|
||||
* bound
|
||||
*/
|
||||
void comtarg(void);
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int cond(int);
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
int32 lo64v(Node*);
|
||||
int32 hi64v(Node*);
|
||||
Node* lo64(Node*);
|
||||
Node* hi64(Node*);
|
||||
|
||||
/*
|
||||
* div/mul
|
||||
*/
|
||||
void sdivgen(Node*, Node*, Node*, Node*);
|
||||
void udivgen(Node*, Node*, Node*, Node*);
|
||||
void sdiv2(int32, int, Node*, Node*);
|
||||
void smod2(int32, int, Node*, Node*);
|
||||
void mulgen(Type*, Node*, Node*);
|
||||
void genmuladd(Node*, Node*, int, Node*);
|
||||
void shiftit(Type*, Node*, Node*);
|
||||
|
||||
/* wrecklessly steal a field */
|
||||
|
||||
#define rplink label
|
@ -1,38 +0,0 @@
|
||||
// Inferno utils/8c/list.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.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.
|
||||
|
||||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
listinit8();
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
// Inferno utils/8c/machcap.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/machcap.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 "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
|
||||
if(n == Z)
|
||||
return 1; /* test */
|
||||
|
||||
switch(n->op) {
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
if(typechl[n->type->etype])
|
||||
return 1;
|
||||
if(typev[n->type->etype]) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
case OASHL:
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
if(typechlv[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(typev[n->type->etype]) {
|
||||
if(typechlp[n->left->type->etype])
|
||||
return 1;
|
||||
}
|
||||
else if(!typefd[n->type->etype]) {
|
||||
if(typev[n->left->type->etype])
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCOND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
return 1;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
return 1;
|
||||
|
||||
case OPOSTINC:
|
||||
case OPOSTDEC:
|
||||
case OPREINC:
|
||||
case OPREDEC:
|
||||
return 1;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OGT:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
458
src/cmd/8c/mul.c
458
src/cmd/8c/mul.c
@ -1,458 +0,0 @@
|
||||
// Inferno utils/8c/mul.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/mul.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 "gc.h"
|
||||
|
||||
typedef struct Malg Malg;
|
||||
typedef struct Mparam Mparam;
|
||||
|
||||
struct Malg
|
||||
{
|
||||
schar vals[10];
|
||||
};
|
||||
|
||||
struct Mparam
|
||||
{
|
||||
uint32 value;
|
||||
schar alg;
|
||||
char neg;
|
||||
char shift;
|
||||
char arg;
|
||||
schar off;
|
||||
};
|
||||
|
||||
static Mparam multab[32];
|
||||
static int mulptr;
|
||||
|
||||
static Malg malgs[] =
|
||||
{
|
||||
{0, 100},
|
||||
{-1, 1, 100},
|
||||
{-9, -5, -3, 3, 5, 9, 100},
|
||||
{6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
|
||||
{-8, -4, -2, 2, 4, 8, 100},
|
||||
};
|
||||
|
||||
/*
|
||||
* return position of lowest 1
|
||||
*/
|
||||
int
|
||||
lowbit(uint32 v)
|
||||
{
|
||||
int s, i;
|
||||
uint32 m;
|
||||
|
||||
s = 0;
|
||||
m = 0xFFFFFFFFUL;
|
||||
for(i = 16; i > 0; i >>= 1) {
|
||||
m >>= i;
|
||||
if((v & m) == 0) {
|
||||
v >>= i;
|
||||
s += i;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
genmuladd(Node *d, Node *s, int m, Node *a)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
nod.op = OINDEX;
|
||||
nod.left = a;
|
||||
nod.right = s;
|
||||
nod.scale = m;
|
||||
nod.type = types[TIND];
|
||||
nod.xoffset = 0;
|
||||
xcom(&nod);
|
||||
gopcode(OADDR, d->type, &nod, d);
|
||||
}
|
||||
|
||||
void
|
||||
mulparam(uint32 m, Mparam *mp)
|
||||
{
|
||||
int c, i, j, n, o, q, s;
|
||||
int bc, bi, bn, bo, bq, bs, bt;
|
||||
schar *p;
|
||||
int32 u;
|
||||
uint32 t;
|
||||
|
||||
bc = bq = 10;
|
||||
bi = bn = bo = bs = bt = 0;
|
||||
for(i = 0; i < nelem(malgs); i++) {
|
||||
for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
|
||||
for(s = 0; s < 2; s++) {
|
||||
c = 10;
|
||||
q = 10;
|
||||
u = m - o;
|
||||
if(u == 0)
|
||||
continue;
|
||||
if(s) {
|
||||
o = -o;
|
||||
if(o > 0)
|
||||
continue;
|
||||
u = -u;
|
||||
}
|
||||
n = lowbit(u);
|
||||
t = (uint32)u >> n;
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(t == 1) {
|
||||
c = s + 1;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = s + 1;
|
||||
if(n)
|
||||
c++;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
if(s)
|
||||
break;
|
||||
switch(t) {
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
c = 2;
|
||||
if(n)
|
||||
c++;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 3;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(s)
|
||||
break;
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(c < bc || (c == bc && q > bq)) {
|
||||
bc = c;
|
||||
bi = i;
|
||||
bn = n;
|
||||
bo = o;
|
||||
bq = q;
|
||||
bs = s;
|
||||
bt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp->value = m;
|
||||
if(bc <= 3) {
|
||||
mp->alg = bi;
|
||||
mp->shift = bn;
|
||||
mp->off = bo;
|
||||
mp->neg = bs;
|
||||
mp->arg = bt;
|
||||
}
|
||||
else
|
||||
mp->alg = -1;
|
||||
}
|
||||
|
||||
int
|
||||
m0(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case -2:
|
||||
case 2:
|
||||
return 2;
|
||||
case -3:
|
||||
case 3:
|
||||
return 2;
|
||||
case -4:
|
||||
case 4:
|
||||
return 4;
|
||||
case -5:
|
||||
case 5:
|
||||
return 4;
|
||||
case 6:
|
||||
return 2;
|
||||
case -8:
|
||||
case 8:
|
||||
return 8;
|
||||
case -9:
|
||||
case 9:
|
||||
return 8;
|
||||
case 10:
|
||||
return 4;
|
||||
case 12:
|
||||
return 2;
|
||||
case 15:
|
||||
return 2;
|
||||
case 18:
|
||||
return 8;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 2;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 2;
|
||||
case 36:
|
||||
return 8;
|
||||
case 40:
|
||||
return 4;
|
||||
case 45:
|
||||
return 4;
|
||||
case 72:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m1(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 15:
|
||||
return 4;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 8;
|
||||
case 45:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m2(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 6:
|
||||
return 2;
|
||||
case 10:
|
||||
return 2;
|
||||
case 12:
|
||||
return 4;
|
||||
case 18:
|
||||
return 2;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 8;
|
||||
case 36:
|
||||
return 4;
|
||||
case 40:
|
||||
return 8;
|
||||
case 72:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shiftit(Type *t, Node *s, Node *d)
|
||||
{
|
||||
int32 c;
|
||||
|
||||
c = (int32)s->vconst & 31;
|
||||
switch(c) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
gopcode(OADD, t, d, d);
|
||||
break;
|
||||
default:
|
||||
gopcode(OASHL, t, s, d);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mulgen1(uint32 v, Node *n)
|
||||
{
|
||||
int i, o;
|
||||
Mparam *p;
|
||||
Node nod, nods;
|
||||
|
||||
for(i = 0; i < nelem(multab); i++) {
|
||||
p = &multab[i];
|
||||
if(p->value == v)
|
||||
goto found;
|
||||
}
|
||||
|
||||
p = &multab[mulptr];
|
||||
if(++mulptr == nelem(multab))
|
||||
mulptr = 0;
|
||||
|
||||
mulparam(v, p);
|
||||
|
||||
found:
|
||||
// print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
|
||||
if(p->alg < 0)
|
||||
return 0;
|
||||
|
||||
nods = *nodconst(p->shift);
|
||||
|
||||
o = OADD;
|
||||
if(p->alg > 0) {
|
||||
regalloc(&nod, n, Z);
|
||||
if(p->off < 0)
|
||||
o = OSUB;
|
||||
}
|
||||
|
||||
switch(p->alg) {
|
||||
case 0:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
genmuladd(n, n, m1(p->arg), n);
|
||||
/* fall thru */
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(n, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg == 1)
|
||||
gins(ANEGL, Z, n);
|
||||
break;
|
||||
case 1:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
gmove(n, &nod);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(&nod, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg)
|
||||
gopcode(o, n->type, &nod, n);
|
||||
else {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
case 3:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
genmuladd(n, &nod, m2(p->off), n);
|
||||
break;
|
||||
case 4:
|
||||
genmuladd(&nod, n, m0(p->off), nodconst(0));
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
default:
|
||||
diag(Z, "bad mul alg");
|
||||
break;
|
||||
comop:
|
||||
if(p->neg) {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
else
|
||||
gopcode(o, n->type, &nod, n);
|
||||
}
|
||||
|
||||
if(p->alg > 0)
|
||||
regfree(&nod);
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
diag(Z, "mulgen botch");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mulgen(Type *t, Node *r, Node *n)
|
||||
{
|
||||
if(!mulgen1(r->vconst, n))
|
||||
gopcode(OMUL, t, r, n);
|
||||
}
|
@ -1,807 +0,0 @@
|
||||
// Inferno utils/8c/peep.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/peep.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 "gc.h"
|
||||
|
||||
static int
|
||||
needc(Prog *p)
|
||||
{
|
||||
while(p != P) {
|
||||
switch(p->as) {
|
||||
case AADCL:
|
||||
case ASBBL:
|
||||
case ARCRL:
|
||||
return 1;
|
||||
case AADDL:
|
||||
case ASUBL:
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case ACALL:
|
||||
return 0;
|
||||
default:
|
||||
if(p->to.type == D_BRANCH)
|
||||
return 0;
|
||||
}
|
||||
p = p->link;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
peep(void)
|
||||
{
|
||||
Reg *r, *r1, *r2;
|
||||
Prog *p, *p1;
|
||||
int t;
|
||||
|
||||
/*
|
||||
* complete R structure
|
||||
*/
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r1) {
|
||||
r1 = r->link;
|
||||
if(r1 == R)
|
||||
break;
|
||||
p = r->prog->link;
|
||||
while(p != r1->prog)
|
||||
switch(p->as) {
|
||||
default:
|
||||
r2 = rega();
|
||||
r->link = r2;
|
||||
r2->link = r1;
|
||||
|
||||
r2->prog = p;
|
||||
r2->p1 = r;
|
||||
r->s1 = r2;
|
||||
r2->s1 = r1;
|
||||
r1->p1 = r2;
|
||||
|
||||
r = r2;
|
||||
t++;
|
||||
|
||||
case ADATA:
|
||||
case AGLOBL:
|
||||
case ANAME:
|
||||
case ASIGNAME:
|
||||
p = p->link;
|
||||
}
|
||||
}
|
||||
|
||||
pc = 0; /* speculating it won't kill */
|
||||
|
||||
loop1:
|
||||
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case AMOVL:
|
||||
if(regtyp(&p->to))
|
||||
if(regtyp(&p->from)) {
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBLSX:
|
||||
case AMOVBLZX:
|
||||
case AMOVWLSX:
|
||||
case AMOVWLZX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = uniqs(r);
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type)
|
||||
p1->as = AMOVL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AADDL:
|
||||
case AADDW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1){
|
||||
if(p->as == AADDL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == AADDL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
case ASUBL:
|
||||
case ASUBW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1) {
|
||||
if(p->as == ASUBL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == ASUBL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(t)
|
||||
goto loop1;
|
||||
}
|
||||
|
||||
void
|
||||
excise(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = r->prog;
|
||||
p->as = ANOP;
|
||||
p->from = zprog.from;
|
||||
p->to = zprog.to;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqp(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->p1;
|
||||
if(r1 == R) {
|
||||
r1 = r->p2;
|
||||
if(r1 == R || r1->p2link != R)
|
||||
return R;
|
||||
} else
|
||||
if(r->p2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqs(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->s1;
|
||||
if(r1 == R) {
|
||||
r1 = r->s2;
|
||||
if(r1 == R)
|
||||
return R;
|
||||
} else
|
||||
if(r->s2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
int
|
||||
regtyp(Addr *a)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = a->type;
|
||||
if(t >= D_AX && t <= D_DI)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the idea is to substitute
|
||||
* one register for another
|
||||
* from one MOV to another
|
||||
* MOV a, R0
|
||||
* ADD b, R0 / no use of R1
|
||||
* MOV R0, R1
|
||||
* would be converted to
|
||||
* MOV a, R1
|
||||
* ADD b, R1
|
||||
* MOV R1, R0
|
||||
* hopefully, then the former or latter MOV
|
||||
* will be eliminated by copy propagation.
|
||||
*/
|
||||
int
|
||||
subprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Addr *v1, *v2;
|
||||
Reg *r;
|
||||
int t;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
if(!regtyp(v1))
|
||||
return 0;
|
||||
v2 = &p->to;
|
||||
if(!regtyp(v2))
|
||||
return 0;
|
||||
for(r=uniqp(r0); r!=R; r=uniqp(r)) {
|
||||
if(uniqs(r) == R)
|
||||
break;
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case ACALL:
|
||||
return 0;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE)
|
||||
break;
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULW:
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRW:
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
case AFSTSW:
|
||||
return 0;
|
||||
|
||||
case AMOVL:
|
||||
if(p->to.type == v1->type)
|
||||
goto gotit;
|
||||
break;
|
||||
}
|
||||
if(copyau(&p->from, v2) ||
|
||||
copyau(&p->to, v2))
|
||||
break;
|
||||
if(copysub(&p->from, v1, v2, 0) ||
|
||||
copysub(&p->to, v1, v2, 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
gotit:
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P']) {
|
||||
print("gotit: %D->%D\n%P", v1, v2, r->prog);
|
||||
if(p->from.type == v2->type)
|
||||
print(" excise");
|
||||
print("\n");
|
||||
}
|
||||
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
|
||||
p = r->prog;
|
||||
copysub(&p->from, v1, v2, 1);
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P'])
|
||||
print("%P\n", r->prog);
|
||||
}
|
||||
t = v1->type;
|
||||
v1->type = v2->type;
|
||||
v2->type = t;
|
||||
if(debug['P'])
|
||||
print("%P last\n", r->prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idea is to remove redundant copies.
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* use v2 return fail
|
||||
* -----------------
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* set v2 return success
|
||||
*/
|
||||
int
|
||||
copyprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Addr *v1, *v2;
|
||||
Reg *r;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
v2 = &p->to;
|
||||
if(copyas(v1, v2))
|
||||
return 1;
|
||||
for(r=firstr; r!=R; r=r->link)
|
||||
r->active = 0;
|
||||
return copy1(v1, v2, r0->s1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
copy1(Addr *v1, Addr *v2, Reg *r, int f)
|
||||
{
|
||||
int t;
|
||||
Prog *p;
|
||||
|
||||
if(r->active) {
|
||||
if(debug['P'])
|
||||
print("act set; return 1\n");
|
||||
return 1;
|
||||
}
|
||||
r->active = 1;
|
||||
if(debug['P'])
|
||||
print("copy %D->%D f=%d\n", v1, v2, f);
|
||||
for(; r != R; r = r->s1) {
|
||||
p = r->prog;
|
||||
if(debug['P'])
|
||||
print("%P", p);
|
||||
if(!f && uniqp(r) == R) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; merge; f=%d", f);
|
||||
}
|
||||
t = copyu(p, v2, A);
|
||||
switch(t) {
|
||||
case 2: /* rar, can't split */
|
||||
if(debug['P'])
|
||||
print("; %D rar; return 0\n", v2);
|
||||
return 0;
|
||||
|
||||
case 3: /* set */
|
||||
if(debug['P'])
|
||||
print("; %D set; return 1\n", v2);
|
||||
return 1;
|
||||
|
||||
case 1: /* used, substitute */
|
||||
case 4: /* use and set */
|
||||
if(f) {
|
||||
if(!debug['P'])
|
||||
return 0;
|
||||
if(t == 4)
|
||||
print("; %D used+set and f=%d; return 0\n", v2, f);
|
||||
else
|
||||
print("; %D used and f=%d; return 0\n", v2, f);
|
||||
return 0;
|
||||
}
|
||||
if(copyu(p, v2, v1)) {
|
||||
if(debug['P'])
|
||||
print("; sub fail; return 0\n");
|
||||
return 0;
|
||||
}
|
||||
if(debug['P'])
|
||||
print("; sub %D/%D", v2, v1);
|
||||
if(t == 4) {
|
||||
if(debug['P'])
|
||||
print("; %D used+set; return 1\n", v2);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!f) {
|
||||
t = copyu(p, v1, A);
|
||||
if(!f && (t == 2 || t == 3 || t == 4)) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; %D set and !f; f=%d", v1, f);
|
||||
}
|
||||
}
|
||||
if(debug['P'])
|
||||
print("\n");
|
||||
if(r->s2)
|
||||
if(!copy1(v1, v2, r->s2, f))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return
|
||||
* 1 if v only used (and substitute),
|
||||
* 2 if read-alter-rewrite
|
||||
* 3 if set
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
copyu(Prog *p, Addr *v, Addr *s)
|
||||
{
|
||||
|
||||
switch(p->as) {
|
||||
|
||||
default:
|
||||
if(debug['P'])
|
||||
print("unknown op %A\n", p->as);
|
||||
return 2;
|
||||
|
||||
case ANEGB:
|
||||
case ANEGW:
|
||||
case ANEGL:
|
||||
case ANOTB:
|
||||
case ANOTW:
|
||||
case ANOTL:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ALEAL: /* lhs addr, rhs store */
|
||||
if(copyas(&p->from, v))
|
||||
return 2;
|
||||
|
||||
|
||||
case ANOP: /* rhs store */
|
||||
case AMOVL:
|
||||
case AMOVBLSX:
|
||||
case AMOVBLZX:
|
||||
case AMOVWLSX:
|
||||
case AMOVWLZX:
|
||||
if(copyas(&p->to, v)) {
|
||||
if(s != A)
|
||||
return copysub(&p->from, v, s, 1);
|
||||
if(copyau(&p->from, v))
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
goto caseread;
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRW:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
if(copyas(&p->from, v))
|
||||
if(p->from.type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AADDB: /* rhs rar */
|
||||
case AADDL:
|
||||
case AADDW:
|
||||
case AANDB:
|
||||
case AANDL:
|
||||
case AANDW:
|
||||
case ADECL:
|
||||
case ADECW:
|
||||
case AINCL:
|
||||
case AINCW:
|
||||
case ASUBB:
|
||||
case ASUBL:
|
||||
case ASUBW:
|
||||
case AORB:
|
||||
case AORL:
|
||||
case AORW:
|
||||
case AXORB:
|
||||
case AXORL:
|
||||
case AXORW:
|
||||
case AMOVB:
|
||||
case AMOVW:
|
||||
|
||||
case AFMOVB:
|
||||
case AFMOVBP:
|
||||
case AFMOVD:
|
||||
case AFMOVDP:
|
||||
case AFMOVF:
|
||||
case AFMOVFP:
|
||||
case AFMOVL:
|
||||
case AFMOVLP:
|
||||
case AFMOVV:
|
||||
case AFMOVVP:
|
||||
case AFMOVW:
|
||||
case AFMOVWP:
|
||||
case AFMOVX:
|
||||
case AFMOVXP:
|
||||
case AFADDDP:
|
||||
case AFADDW:
|
||||
case AFADDL:
|
||||
case AFADDF:
|
||||
case AFADDD:
|
||||
case AFMULDP:
|
||||
case AFMULW:
|
||||
case AFMULL:
|
||||
case AFMULF:
|
||||
case AFMULD:
|
||||
case AFSUBDP:
|
||||
case AFSUBW:
|
||||
case AFSUBL:
|
||||
case AFSUBF:
|
||||
case AFSUBD:
|
||||
case AFSUBRDP:
|
||||
case AFSUBRW:
|
||||
case AFSUBRL:
|
||||
case AFSUBRF:
|
||||
case AFSUBRD:
|
||||
case AFDIVDP:
|
||||
case AFDIVW:
|
||||
case AFDIVL:
|
||||
case AFDIVF:
|
||||
case AFDIVD:
|
||||
case AFDIVRDP:
|
||||
case AFDIVRW:
|
||||
case AFDIVRL:
|
||||
case AFDIVRF:
|
||||
case AFDIVRD:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ACMPL: /* read only */
|
||||
case ACMPW:
|
||||
case ACMPB:
|
||||
|
||||
case APREFETCHT0:
|
||||
case APREFETCHT1:
|
||||
case APREFETCHT2:
|
||||
case APREFETCHNTA:
|
||||
|
||||
|
||||
case AFCOMB:
|
||||
case AFCOMBP:
|
||||
case AFCOMD:
|
||||
case AFCOMDP:
|
||||
case AFCOMDPP:
|
||||
case AFCOMF:
|
||||
case AFCOMFP:
|
||||
case AFCOML:
|
||||
case AFCOMLP:
|
||||
case AFCOMW:
|
||||
case AFCOMWP:
|
||||
case AFUCOM:
|
||||
case AFUCOMP:
|
||||
case AFUCOMPP:
|
||||
caseread:
|
||||
if(s != A) {
|
||||
if(copysub(&p->from, v, s, 1))
|
||||
return 1;
|
||||
return copysub(&p->to, v, s, 1);
|
||||
}
|
||||
if(copyau(&p->from, v))
|
||||
return 1;
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case AJGE: /* no reference */
|
||||
case AJNE:
|
||||
case AJLE:
|
||||
case AJEQ:
|
||||
case AJHI:
|
||||
case AJLS:
|
||||
case AJMI:
|
||||
case AJPL:
|
||||
case AJGT:
|
||||
case AJLT:
|
||||
case AJCC:
|
||||
case AJCS:
|
||||
|
||||
case AADJSP:
|
||||
case AFLDZ:
|
||||
case AWAIT:
|
||||
break;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE) {
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
}
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULW:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
if(v->type == D_AX || v->type == D_DX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
if(v->type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
if(v->type == D_DI || v->type == D_SI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
if(v->type == D_AX || v->type == D_DI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AFSTSW:
|
||||
if(v->type == D_AX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AJMP: /* funny */
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case ARET: /* funny */
|
||||
if(v->type == REGRET)
|
||||
return 2;
|
||||
if(s != A)
|
||||
return 1;
|
||||
return 3;
|
||||
|
||||
case ACALL: /* funny */
|
||||
if(REGARG >= 0 && v->type == (uchar)REGARG)
|
||||
return 2;
|
||||
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* direct reference,
|
||||
* could be set/use depending on
|
||||
* semantics
|
||||
*/
|
||||
int
|
||||
copyas(Addr *a, Addr *v)
|
||||
{
|
||||
if(a->type != v->type)
|
||||
return 0;
|
||||
if(regtyp(v))
|
||||
return 1;
|
||||
if(v->type == D_AUTO || v->type == D_PARAM)
|
||||
if(v->offset == a->offset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* either direct or indirect
|
||||
*/
|
||||
int
|
||||
copyau(Addr *a, Addr *v)
|
||||
{
|
||||
|
||||
if(copyas(a, v))
|
||||
return 1;
|
||||
if(regtyp(v)) {
|
||||
if(a->type-D_INDIR == v->type)
|
||||
return 1;
|
||||
if(a->index == v->type)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* substitute s for v in a
|
||||
* return failure to substitute
|
||||
*/
|
||||
int
|
||||
copysub(Addr *a, Addr *v, Addr *s, int f)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(copyas(a, v)) {
|
||||
t = s->type;
|
||||
if(t >= D_AX && t <= D_DI) {
|
||||
if(f)
|
||||
a->type = t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(regtyp(v)) {
|
||||
t = v->type;
|
||||
if(a->type == t+D_INDIR) {
|
||||
if(s->type == D_BP && a->index != D_NONE)
|
||||
return 1; /* can't use BP-base with index */
|
||||
if(f)
|
||||
a->type = s->type+D_INDIR;
|
||||
// return 0;
|
||||
}
|
||||
if(a->index == t) {
|
||||
if(f)
|
||||
a->index = s->type;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
1438
src/cmd/8c/reg.c
1438
src/cmd/8c/reg.c
File diff suppressed because it is too large
Load Diff
@ -1,483 +0,0 @@
|
||||
// Inferno utils/8c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.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 "gc.h"
|
||||
|
||||
Prog*
|
||||
gtext(Sym *s, int32 stkoff)
|
||||
{
|
||||
int32 a;
|
||||
|
||||
a = argsize(1);
|
||||
if((textflag & NOSPLIT) != 0 && stkoff >= 128)
|
||||
yyerror("stack frame too large for NOSPLIT function");
|
||||
|
||||
gpseudo(ATEXT, s, nodconst(stkoff));
|
||||
p->to.type = D_CONST2;
|
||||
p->to.offset2 = a;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome to commute */
|
||||
static void
|
||||
commute(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(r->complex > l->complex) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indexshift(Node *n)
|
||||
{
|
||||
int g;
|
||||
|
||||
if(!typechlp[n->type->etype])
|
||||
return;
|
||||
simplifyshift(n);
|
||||
if(n->op == OASHL && n->right->op == OCONST){
|
||||
g = vconst(n->right);
|
||||
if(g >= 0 && g < 4)
|
||||
n->addable = 7;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* NAME ==> 10/11 name+value(SB/SP)
|
||||
* REGISTER ==> 12 register
|
||||
* CONST ==> 20 $value
|
||||
* *(20) ==> 21 value
|
||||
* &(10) ==> 13 $name+value(SB)
|
||||
* &(11) ==> 1 $name+value(SP)
|
||||
* (13) + (20) ==> 13 fold constants
|
||||
* (1) + (20) ==> 1 fold constants
|
||||
* *(13) ==> 10 back to name
|
||||
* *(1) ==> 11 back to name
|
||||
*
|
||||
* (20) * (X) ==> 7 multiplier in indexing
|
||||
* (X,7) + (13,1) ==> 8 adder in indexing (addresses)
|
||||
* (8) ==> &9(OINDEX) index, almost addressable
|
||||
* 100 extern register
|
||||
*
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int g;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->complex = 0;
|
||||
n->addable = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 10;
|
||||
if(n->class == CPARAM || n->class == CAUTO)
|
||||
n->addable = 11;
|
||||
break;
|
||||
|
||||
case OEXREG:
|
||||
n->addable = 0;
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 13;
|
||||
else
|
||||
if(l->addable == 11)
|
||||
n->addable = 1;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(n->type->etype != TIND)
|
||||
break;
|
||||
|
||||
switch(r->addable) {
|
||||
case 20:
|
||||
switch(l->addable) {
|
||||
case 1:
|
||||
case 13:
|
||||
commadd:
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
l = new(0, Z, Z);
|
||||
*l = *(n->left);
|
||||
l->xoffset += r->vconst;
|
||||
n->left = l;
|
||||
r = n->right;
|
||||
goto brk;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 13:
|
||||
case 10:
|
||||
case 11:
|
||||
/* l is the base, r is the index */
|
||||
if(l->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
switch(r->addable) {
|
||||
case 13:
|
||||
case 1:
|
||||
r = n->left;
|
||||
l = n->right;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
goto commadd;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
case 1:
|
||||
case 10:
|
||||
case 11:
|
||||
/* r is the base, l is the index */
|
||||
if(r->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
if(n->addable == 8 && !side(n)) {
|
||||
indx(n);
|
||||
l = new1(OINDEX, idx.basetree, idx.regtree);
|
||||
l->scale = idx.scale;
|
||||
l->addable = 9;
|
||||
l->complex = l->right->complex;
|
||||
l->type = l->left->type;
|
||||
n->op = OADDR;
|
||||
n->left = l;
|
||||
n->right = Z;
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OINDEX:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
n->addable = 9;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->op == OADDR) {
|
||||
l = l->left;
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
return;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
n->addable = 21;
|
||||
break;
|
||||
case 1:
|
||||
n->addable = 11;
|
||||
break;
|
||||
case 13:
|
||||
n->addable = 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(l);
|
||||
if(g >= 0) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
commute(n);
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = g;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
brk:
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
if(com64(n))
|
||||
return;
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
case OMOD:
|
||||
case OLMUL:
|
||||
case OLDIV:
|
||||
case OMUL:
|
||||
case ODIV:
|
||||
case OASLMUL:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASMUL:
|
||||
case OASDIV:
|
||||
case OASMOD:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 3;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 3;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case OASLSHR:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 2;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 2;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
/*
|
||||
* compare operators, make const on left
|
||||
*/
|
||||
if(r->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
n->op = invrel[relindex(n->op)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indx(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(debug['x'])
|
||||
prtree(n, "indx");
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
|
||||
n->right = l;
|
||||
n->left = r;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
if(l->addable != 7) {
|
||||
idx.regtree = l;
|
||||
idx.scale = 1;
|
||||
} else
|
||||
if(l->right->addable == 20) {
|
||||
idx.regtree = l->left;
|
||||
idx.scale = 1 << l->right->vconst;
|
||||
} else
|
||||
if(l->left->addable == 20) {
|
||||
idx.regtree = l->right;
|
||||
idx.scale = 1 << l->left->vconst;
|
||||
} else
|
||||
diag(n, "bad index");
|
||||
|
||||
idx.basetree = r;
|
||||
if(debug['x']) {
|
||||
print("scale = %d\n", idx.scale);
|
||||
prtree(idx.regtree, "index");
|
||||
prtree(idx.basetree, "base");
|
||||
}
|
||||
}
|
341
src/cmd/8c/swt.c
341
src/cmd/8c/swt.c
@ -1,341 +0,0 @@
|
||||
// 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 "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
Node nreg;
|
||||
|
||||
if(typev[n->type->etype]) {
|
||||
regsalloc(&nreg, n);
|
||||
nreg.type = types[TVLONG];
|
||||
cgen(n, &nreg);
|
||||
swit2(q, nc, def, &nreg);
|
||||
return;
|
||||
}
|
||||
|
||||
regalloc(&nreg, n, Z);
|
||||
nreg.type = types[TLONG];
|
||||
cgen(n, &nreg);
|
||||
swit2(q, nc, def, &nreg);
|
||||
regfree(&nreg);
|
||||
}
|
||||
|
||||
void
|
||||
swit2(C1 *q, int nc, int32 def, Node *n)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
Prog *sp;
|
||||
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8ux\n", q->val);
|
||||
gopcode(OEQ, n->type, n, nodconst(q->val));
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8ux\n", r->val);
|
||||
gopcode(OGT, n->type, n, nodconst(r->val));
|
||||
sp = p;
|
||||
gbranch(OGOTO);
|
||||
p->as = AJEQ;
|
||||
patch(p, r->label);
|
||||
swit2(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8ux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
int32 v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gmove(n2, n3);
|
||||
gmove(n3, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, types[TLONG], nodconst(v), n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, types[TLONG], nodconst(sh), n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
|
||||
else
|
||||
gopcode(OASHR, types[TLONG], nodconst(sh), n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int32 v;
|
||||
Node nod;
|
||||
int sh;
|
||||
|
||||
regalloc(&nod, b->left, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, types[TLONG], nodconst(v), n1);
|
||||
gmove(n1, &nod);
|
||||
if(nn != Z)
|
||||
gmove(n1, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, types[TLONG], nodconst(~v), n3);
|
||||
gopcode(OOR, types[TLONG], n3, &nod);
|
||||
gmove(&nod, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
int32
|
||||
outstring(char *s, int32 n)
|
||||
{
|
||||
int32 r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->from.scale = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
int32 e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0L));
|
||||
p->from.offset += o+e;
|
||||
p->from.scale = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.u.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, int32 o, int32 w)
|
||||
{
|
||||
if(a->op == OCONST && typev[a->type->etype]) {
|
||||
gpseudo(ADATA, s, lo64(a));
|
||||
p->from.offset += o;
|
||||
p->from.scale = 4;
|
||||
gpseudo(ADATA, s, hi64(a));
|
||||
p->from.offset += o + 4;
|
||||
p->from.scale = 4;
|
||||
return;
|
||||
}
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->from.scale = w;
|
||||
switch(p->to.type) {
|
||||
default:
|
||||
p->to.index = p->to.type;
|
||||
p->to.type = D_ADDR;
|
||||
case D_CONST:
|
||||
case D_FCONST:
|
||||
case D_ADDR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
int f;
|
||||
Biobuf b;
|
||||
|
||||
f = open(outfile, OWRITE);
|
||||
if(f < 0) {
|
||||
diag(Z, "cannot open %s", outfile);
|
||||
return;
|
||||
}
|
||||
Binit(&b, f, OWRITE);
|
||||
|
||||
Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
|
||||
if(pragcgobuf.to > pragcgobuf.start) {
|
||||
Bprint(&b, "\n");
|
||||
Bprint(&b, "$$ // exports\n\n");
|
||||
Bprint(&b, "$$ // local types\n\n");
|
||||
Bprint(&b, "$$ // cgo\n");
|
||||
Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
|
||||
Bprint(&b, "\n$$\n\n");
|
||||
}
|
||||
Bprint(&b, "!\n");
|
||||
|
||||
writeobj(ctxt, &b);
|
||||
Bterm(&b);
|
||||
close(f);
|
||||
lastp = P;
|
||||
}
|
||||
|
||||
int32
|
||||
align(int32 i, Type *t, int op, int32 *maxalign)
|
||||
{
|
||||
int32 o;
|
||||
Type *v;
|
||||
int w, packw;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
packw = 0;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = *maxalign;
|
||||
if(w < 1)
|
||||
w = 1;
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
if(v->etype == TSTRUCT || v->etype == TUNION)
|
||||
w = v->align;
|
||||
else {
|
||||
w = ewidth[v->etype];
|
||||
if(w == 8)
|
||||
w = 4;
|
||||
}
|
||||
if(w < 1 || w > SZ_LONG)
|
||||
fatal(Z, "align");
|
||||
if(packflg)
|
||||
packw = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesuv[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1, nil);
|
||||
o = align(o, types[TIND], Aarg2, nil);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_LONG) {
|
||||
w = SZ_LONG;
|
||||
break;
|
||||
}
|
||||
w = 1; /* little endian no adjustment */
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
w = t->width;
|
||||
if(w > SZ_LONG)
|
||||
w = SZ_LONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total align of automatic */
|
||||
o = align(o, t, Ael1, nil);
|
||||
o = align(o, t, Ael2, nil);
|
||||
break;
|
||||
}
|
||||
if(packw != 0 && xround(o, w) != xround(o, packw))
|
||||
diag(Z, "#pragma pack changes offset of %T", t);
|
||||
o = xround(o, w);
|
||||
if(maxalign && *maxalign < w)
|
||||
*maxalign = w;
|
||||
if(debug['A'])
|
||||
print("align %s %d %T = %d\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int32
|
||||
maxround(int32 max, int32 v)
|
||||
{
|
||||
v = xround(v, SZ_LONG);
|
||||
if(v > max)
|
||||
return v;
|
||||
return max;
|
||||
}
|
1537
src/cmd/8c/txt.c
1537
src/cmd/8c/txt.c
File diff suppressed because it is too large
Load Diff
@ -1,10 +0,0 @@
|
||||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
include ../../Make.dist
|
||||
|
||||
install: y.tab.h
|
||||
|
||||
y.tab.h: cc.y
|
||||
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y cc.y
|
@ -1,344 +0,0 @@
|
||||
// Inferno utils/cc/acid.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/acid.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 "cc.h"
|
||||
|
||||
static char *kwd[] =
|
||||
{
|
||||
"$adt", "$aggr", "$append", "$complex", "$defn",
|
||||
"$delete", "$do", "$else", "$eval", "$head", "$if",
|
||||
"$local", "$loop", "$return", "$tail", "$then",
|
||||
"$union", "$whatis", "$while",
|
||||
};
|
||||
|
||||
char*
|
||||
amap(char *s)
|
||||
{
|
||||
int i, bot, top, new;
|
||||
|
||||
bot = 0;
|
||||
top = bot + nelem(kwd) - 1;
|
||||
while(bot <= top){
|
||||
new = bot + (top - bot)/2;
|
||||
i = strcmp(kwd[new]+1, s);
|
||||
if(i == 0)
|
||||
return kwd[new];
|
||||
|
||||
if(i < 0)
|
||||
bot = new + 1;
|
||||
else
|
||||
top = new - 1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Sym*
|
||||
acidsue(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
if(t != T)
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->suetag && s->suetag->link == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sym*
|
||||
acidfun(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->type == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char acidchar[NTYPE];
|
||||
Init acidcinit[] =
|
||||
{
|
||||
TCHAR, 'C', 0,
|
||||
TUCHAR, 'b', 0,
|
||||
TSHORT, 'd', 0,
|
||||
TUSHORT, 'u', 0,
|
||||
TLONG, 'D', 0,
|
||||
TULONG, 'U', 0,
|
||||
TVLONG, 'V', 0,
|
||||
TUVLONG, 'W', 0,
|
||||
TFLOAT, 'f', 0,
|
||||
TDOUBLE, 'F', 0,
|
||||
TARRAY, 'a', 0,
|
||||
TIND, 'X', 0,
|
||||
-1, 0, 0,
|
||||
};
|
||||
|
||||
static void
|
||||
acidinit(void)
|
||||
{
|
||||
Init *p;
|
||||
|
||||
for(p=acidcinit; p->code >= 0; p++)
|
||||
acidchar[p->code] = p->value;
|
||||
|
||||
acidchar[TINT] = acidchar[TLONG];
|
||||
acidchar[TUINT] = acidchar[TULONG];
|
||||
if(types[TINT]->width != types[TLONG]->width) {
|
||||
acidchar[TINT] = acidchar[TSHORT];
|
||||
acidchar[TUINT] = acidchar[TUSHORT];
|
||||
if(types[TINT]->width != types[TSHORT]->width)
|
||||
warn(Z, "acidmember int not long or short");
|
||||
}
|
||||
if(types[TIND]->width == types[TUVLONG]->width)
|
||||
acidchar[TIND] = 'Y';
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
acidmember(Type *t, int32 off, int flag)
|
||||
{
|
||||
Sym *s, *s1;
|
||||
Type *l;
|
||||
static int acidcharinit = 0;
|
||||
|
||||
if(acidcharinit == 0) {
|
||||
acidinit();
|
||||
acidcharinit = 1;
|
||||
}
|
||||
s = t->sym;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, " T%d\n", t->etype);
|
||||
break;
|
||||
|
||||
case TIND:
|
||||
if(s == S)
|
||||
break;
|
||||
l = t->link;
|
||||
if(flag) {
|
||||
if(typesu[l->etype]) {
|
||||
s1 = acidsue(l->link);
|
||||
if(s1 != S) {
|
||||
Bprint(&outbuf, " 'A' %s %d %s;\n",
|
||||
amap(s1->name),
|
||||
t->offset+off, amap(s->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
l = t->link;
|
||||
s1 = S;
|
||||
if(typesu[l->etype])
|
||||
s1 = acidsue(l->link);
|
||||
if(s1 != S) {
|
||||
Bprint(&outbuf,
|
||||
"\tprint(indent, \"%s\t(%s)\", addr.%s\\X, \"\\n\");\n",
|
||||
amap(s->name), amap(s1->name), amap(s->name));
|
||||
} else {
|
||||
Bprint(&outbuf,
|
||||
"\tprint(indent, \"%s\t\", addr.%s\\X, \"\\n\");\n",
|
||||
amap(s->name), amap(s->name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TINT:
|
||||
case TUINT:
|
||||
case TCHAR:
|
||||
case TUCHAR:
|
||||
case TSHORT:
|
||||
case TUSHORT:
|
||||
case TLONG:
|
||||
case TULONG:
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
case TARRAY:
|
||||
if(s == S)
|
||||
break;
|
||||
if(flag) {
|
||||
Bprint(&outbuf, " '%c' %d %s;\n",
|
||||
acidchar[t->etype], t->offset+off, amap(s->name));
|
||||
} else {
|
||||
Bprint(&outbuf, "\tprint(indent, \"%s\t\", addr.%s, \"\\n\");\n",
|
||||
amap(s->name), amap(s->name));
|
||||
}
|
||||
break;
|
||||
|
||||
case TSTRUCT:
|
||||
case TUNION:
|
||||
s1 = acidsue(t->link);
|
||||
if(s1 == S)
|
||||
break;
|
||||
if(flag) {
|
||||
if(s == S) {
|
||||
Bprint(&outbuf, " {\n");
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, t->offset+off, flag);
|
||||
Bprint(&outbuf, " };\n");
|
||||
} else {
|
||||
Bprint(&outbuf, " %s %d %s;\n",
|
||||
amap(s1->name),
|
||||
t->offset+off, amap(s->name));
|
||||
}
|
||||
} else {
|
||||
if(s != S) {
|
||||
Bprint(&outbuf, "\tprint(indent, \"%s %s {\\n\");\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
Bprint(&outbuf, "\tindent_%s(addr.%s, indent+\"\\t\");\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
|
||||
} else {
|
||||
Bprint(&outbuf, "\tprint(indent, \"%s {\\n\");\n",
|
||||
amap(s1->name));
|
||||
Bprint(&outbuf, "\tindent_%s(addr+%d, indent+\"\\t\");\n",
|
||||
amap(s1->name), t->offset+off);
|
||||
Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
acidtype(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
Type *l;
|
||||
Io *i;
|
||||
int n;
|
||||
char *an;
|
||||
|
||||
if(!debug['a'])
|
||||
return;
|
||||
if(debug['a'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
s = acidsue(t->link);
|
||||
if(s == S)
|
||||
return;
|
||||
switch(t->etype) {
|
||||
default:
|
||||
Bprint(&outbuf, "T%d\n", t->etype);
|
||||
return;
|
||||
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
if(debug['s'])
|
||||
goto asmstr;
|
||||
an = amap(s->name);
|
||||
Bprint(&outbuf, "sizeof%s = %d;\n", an, t->width);
|
||||
Bprint(&outbuf, "aggr %s\n{\n", an);
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, 0, 1);
|
||||
Bprint(&outbuf, "};\n\n");
|
||||
|
||||
Bprint(&outbuf, "defn\n%s(addr) {\n\tindent_%s(addr, \"\\t\");\n}\n", an, an);
|
||||
Bprint(&outbuf, "defn\nindent_%s(addr, indent) {\n\tcomplex %s addr;\n", an, an);
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
acidmember(l, 0, 0);
|
||||
Bprint(&outbuf, "};\n\n");
|
||||
break;
|
||||
asmstr:
|
||||
if(s == S)
|
||||
break;
|
||||
for(l = t->link; l != T; l = l->down)
|
||||
if(l->sym != S)
|
||||
Bprint(&outbuf, "#define\t%s.%s\t%d\n",
|
||||
s->name,
|
||||
l->sym->name,
|
||||
l->offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
acidvar(Sym *s)
|
||||
{
|
||||
int n;
|
||||
Io *i;
|
||||
Type *t;
|
||||
Sym *s1, *s2;
|
||||
|
||||
if(!debug['a'] || debug['s'])
|
||||
return;
|
||||
if(debug['a'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return;
|
||||
}
|
||||
t = s->type;
|
||||
while(t && t->etype == TIND)
|
||||
t = t->link;
|
||||
if(t == T)
|
||||
return;
|
||||
if(t->etype == TENUM) {
|
||||
Bprint(&outbuf, "%s = ", amap(s->name));
|
||||
if(!typefd[t->etype])
|
||||
Bprint(&outbuf, "%lld;\n", s->vconst);
|
||||
else
|
||||
Bprint(&outbuf, "%f\n;", s->fconst);
|
||||
return;
|
||||
}
|
||||
if(!typesu[t->etype])
|
||||
return;
|
||||
s1 = acidsue(t->link);
|
||||
if(s1 == S)
|
||||
return;
|
||||
switch(s->class) {
|
||||
case CAUTO:
|
||||
case CPARAM:
|
||||
s2 = acidfun(thisfn);
|
||||
if(s2)
|
||||
Bprint(&outbuf, "complex %s %s:%s;\n",
|
||||
amap(s1->name), amap(s2->name), amap(s->name));
|
||||
break;
|
||||
|
||||
case CSTATIC:
|
||||
case CEXTERN:
|
||||
case CGLOBL:
|
||||
case CLOCAL:
|
||||
Bprint(&outbuf, "complex %s %s;\n",
|
||||
amap(s1->name), amap(s->name));
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
// Inferno utils/cc/bits.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.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 "cc.h"
|
||||
|
||||
Bits
|
||||
bor(Bits a, Bits b)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = a.b[i] | b.b[i];
|
||||
return c;
|
||||
}
|
||||
|
||||
Bits
|
||||
band(Bits a, Bits b)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = a.b[i] & b.b[i];
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
Bits
|
||||
bnot(Bits a)
|
||||
{
|
||||
Bits c;
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
c.b[i] = ~a.b[i];
|
||||
return c;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
bany(Bits *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(a->b[i])
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
beq(Bits a, Bits b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(a.b[i] != b.b[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
bnum(Bits a)
|
||||
{
|
||||
int i;
|
||||
int32 b;
|
||||
|
||||
for(i=0; i<BITS; i++)
|
||||
if(b = a.b[i])
|
||||
return 32*i + bitno(b);
|
||||
diag(Z, "bad in bnum");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bits
|
||||
blsh(uint n)
|
||||
{
|
||||
Bits c;
|
||||
|
||||
c = zbits;
|
||||
c.b[n/32] = 1L << (n%32);
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
bset(Bits a, uint n)
|
||||
{
|
||||
if(a.b[n/32] & (1L << (n%32)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
835
src/cmd/cc/cc.h
835
src/cmd/cc/cc.h
@ -1,835 +0,0 @@
|
||||
// Inferno utils/cc/cc.h
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.h
|
||||
//
|
||||
// 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 <libc.h>
|
||||
#include <bio.h>
|
||||
#include <link.h>
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#undef getc
|
||||
#undef ungetc
|
||||
#undef BUFSIZ
|
||||
|
||||
#define getc ccgetc
|
||||
#define ungetc ccungetc
|
||||
|
||||
typedef struct Node Node;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Type Type;
|
||||
typedef struct Funct Funct;
|
||||
typedef struct Decl Decl;
|
||||
typedef struct Io Io;
|
||||
typedef struct Term Term;
|
||||
typedef struct Init Init;
|
||||
typedef struct Bits Bits;
|
||||
typedef struct Bvec Bvec;
|
||||
typedef struct Dynimp Dynimp;
|
||||
typedef struct Dynexp Dynexp;
|
||||
typedef struct Var Var;
|
||||
|
||||
typedef Rune TRune; /* target system type */
|
||||
|
||||
#define BUFSIZ 8192
|
||||
#define NSYMB 500
|
||||
#define NHASH 1024
|
||||
#define STRINGSZ 200
|
||||
#define HISTSZ 20
|
||||
#define YYMAXDEPTH 500
|
||||
#define NTERM 10
|
||||
#define MAXALIGN 7
|
||||
|
||||
#define SIGN(n) ((uvlong)1<<(n-1))
|
||||
#define MASK(n) (SIGN(n)|(SIGN(n)-1))
|
||||
|
||||
#define BITS 5
|
||||
#define NVAR (BITS*sizeof(uint32)*8)
|
||||
struct Bits
|
||||
{
|
||||
uint32 b[BITS];
|
||||
};
|
||||
|
||||
struct Bvec
|
||||
{
|
||||
int32 n; // number of bits
|
||||
uint32 b[];
|
||||
};
|
||||
|
||||
struct Var
|
||||
{
|
||||
vlong offset;
|
||||
LSym* sym;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
Node* left;
|
||||
Node* right;
|
||||
void* label;
|
||||
int32 pc;
|
||||
int reg;
|
||||
int32 xoffset;
|
||||
double fconst; /* fp constant */
|
||||
vlong vconst; /* non fp const */
|
||||
char* cstring; /* character string */
|
||||
TRune* rstring; /* rune string */
|
||||
|
||||
Sym* sym;
|
||||
Type* type;
|
||||
int32 lineno;
|
||||
uchar op;
|
||||
uchar oldop;
|
||||
uchar xcast;
|
||||
uchar class;
|
||||
uchar etype;
|
||||
uchar complex;
|
||||
uchar addable;
|
||||
uchar scale;
|
||||
uchar garb;
|
||||
};
|
||||
#define Z ((Node*)0)
|
||||
|
||||
struct Sym
|
||||
{
|
||||
Sym* link;
|
||||
LSym* lsym;
|
||||
Type* type;
|
||||
Type* suetag;
|
||||
Type* tenum;
|
||||
char* macro;
|
||||
int32 varlineno;
|
||||
int32 offset;
|
||||
vlong vconst;
|
||||
double fconst;
|
||||
Node* label;
|
||||
ushort lexical;
|
||||
char *name;
|
||||
ushort block;
|
||||
ushort sueblock;
|
||||
uchar class;
|
||||
uchar sym;
|
||||
uchar aused;
|
||||
uchar sig;
|
||||
uchar dataflag;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
enum{
|
||||
SIGNONE = 0,
|
||||
SIGDONE = 1,
|
||||
SIGINTERN = 2,
|
||||
|
||||
SIGNINTERN = 1729*325*1729,
|
||||
};
|
||||
|
||||
struct Decl
|
||||
{
|
||||
Decl* link;
|
||||
Sym* sym;
|
||||
Type* type;
|
||||
int32 varlineno;
|
||||
int32 offset;
|
||||
short val;
|
||||
ushort block;
|
||||
uchar class;
|
||||
uchar aused;
|
||||
};
|
||||
#define D ((Decl*)0)
|
||||
|
||||
struct Type
|
||||
{
|
||||
Sym* sym;
|
||||
Sym* tag;
|
||||
Funct* funct;
|
||||
Type* link;
|
||||
Type* down;
|
||||
int32 width;
|
||||
int32 offset;
|
||||
int32 lineno;
|
||||
uchar shift;
|
||||
uchar nbits;
|
||||
uchar etype;
|
||||
uchar garb;
|
||||
uchar align;
|
||||
};
|
||||
|
||||
#define T ((Type*)0)
|
||||
#define NODECL ((void(*)(int, Type*, Sym*))0)
|
||||
|
||||
struct Init /* general purpose initialization */
|
||||
{
|
||||
int code;
|
||||
uint32 value;
|
||||
char* s;
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
char* p;
|
||||
int c;
|
||||
} fi;
|
||||
|
||||
struct Io
|
||||
{
|
||||
Io* link;
|
||||
char* p;
|
||||
char b[BUFSIZ];
|
||||
short c;
|
||||
short f;
|
||||
};
|
||||
#define I ((Io*)0)
|
||||
|
||||
struct Term
|
||||
{
|
||||
vlong mult;
|
||||
Node *node;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Axxx,
|
||||
Ael1,
|
||||
Ael2,
|
||||
Asu2,
|
||||
Aarg0,
|
||||
Aarg1,
|
||||
Aarg2,
|
||||
Aaut3,
|
||||
NALIGN,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DMARK,
|
||||
DAUTO,
|
||||
DSUE,
|
||||
DLABEL,
|
||||
};
|
||||
enum
|
||||
{
|
||||
OXXX,
|
||||
OADD,
|
||||
OADDR,
|
||||
OAND,
|
||||
OANDAND,
|
||||
OARRAY,
|
||||
OAS,
|
||||
OASI,
|
||||
OASADD,
|
||||
OASAND,
|
||||
OASASHL,
|
||||
OASASHR,
|
||||
OASDIV,
|
||||
OASHL,
|
||||
OASHR,
|
||||
OASLDIV,
|
||||
OASLMOD,
|
||||
OASLMUL,
|
||||
OASLSHR,
|
||||
OASMOD,
|
||||
OASMUL,
|
||||
OASOR,
|
||||
OASSUB,
|
||||
OASXOR,
|
||||
OBIT,
|
||||
OBREAK,
|
||||
OCASE,
|
||||
OCAST,
|
||||
OCOMMA,
|
||||
OCOND,
|
||||
OCONST,
|
||||
OCONTINUE,
|
||||
ODIV,
|
||||
ODOT,
|
||||
ODOTDOT,
|
||||
ODWHILE,
|
||||
OENUM,
|
||||
OEQ,
|
||||
OEXREG,
|
||||
OFOR,
|
||||
OFUNC,
|
||||
OGE,
|
||||
OGOTO,
|
||||
OGT,
|
||||
OHI,
|
||||
OHS,
|
||||
OIF,
|
||||
OIND,
|
||||
OINDREG,
|
||||
OINIT,
|
||||
OLABEL,
|
||||
OLDIV,
|
||||
OLE,
|
||||
OLIST,
|
||||
OLMOD,
|
||||
OLMUL,
|
||||
OLO,
|
||||
OLS,
|
||||
OLSHR,
|
||||
OLT,
|
||||
OMOD,
|
||||
OMUL,
|
||||
ONAME,
|
||||
ONE,
|
||||
ONOT,
|
||||
OOR,
|
||||
OOROR,
|
||||
OPOSTDEC,
|
||||
OPOSTINC,
|
||||
OPREDEC,
|
||||
OPREINC,
|
||||
OPREFETCH,
|
||||
OPROTO,
|
||||
OREGISTER,
|
||||
ORETURN,
|
||||
OSET,
|
||||
OSIGN,
|
||||
OSIZE,
|
||||
OSTRING,
|
||||
OLSTRING,
|
||||
OSTRUCT,
|
||||
OSUB,
|
||||
OSWITCH,
|
||||
OUNION,
|
||||
OUSED,
|
||||
OWHILE,
|
||||
OXOR,
|
||||
ONEG,
|
||||
OCOM,
|
||||
OPOS,
|
||||
OELEM,
|
||||
|
||||
OTST, /* used in some compilers */
|
||||
OINDEX,
|
||||
OFAS,
|
||||
OREGPAIR,
|
||||
OROTL,
|
||||
|
||||
OEND
|
||||
};
|
||||
enum
|
||||
{
|
||||
TXXX,
|
||||
TCHAR,
|
||||
TUCHAR,
|
||||
TSHORT,
|
||||
TUSHORT,
|
||||
TINT,
|
||||
TUINT,
|
||||
TLONG,
|
||||
TULONG,
|
||||
TVLONG,
|
||||
TUVLONG,
|
||||
TFLOAT,
|
||||
TDOUBLE,
|
||||
TIND,
|
||||
TFUNC,
|
||||
TARRAY,
|
||||
TVOID,
|
||||
TSTRUCT,
|
||||
TUNION,
|
||||
TENUM,
|
||||
NTYPE,
|
||||
|
||||
TAUTO = NTYPE,
|
||||
TEXTERN,
|
||||
TSTATIC,
|
||||
TTYPEDEF,
|
||||
TTYPESTR,
|
||||
TREGISTER,
|
||||
TCONSTNT,
|
||||
TVOLATILE,
|
||||
TUNSIGNED,
|
||||
TSIGNED,
|
||||
TDOT,
|
||||
TFILE,
|
||||
TOLD,
|
||||
NALLTYPES,
|
||||
|
||||
/* adapt size of Rune to target system's size */
|
||||
TRUNE = sizeof(TRune)==4? TUINT: TUSHORT,
|
||||
};
|
||||
enum
|
||||
{
|
||||
CXXX,
|
||||
CAUTO,
|
||||
CEXTERN,
|
||||
CGLOBL,
|
||||
CSTATIC,
|
||||
CLOCAL,
|
||||
CTYPEDEF,
|
||||
CTYPESTR,
|
||||
CPARAM,
|
||||
CSELEM,
|
||||
CLABEL,
|
||||
CEXREG,
|
||||
NCTYPES,
|
||||
};
|
||||
enum
|
||||
{
|
||||
GXXX = 0,
|
||||
GCONSTNT = 1<<0,
|
||||
GVOLATILE = 1<<1,
|
||||
NGTYPES = 1<<2,
|
||||
|
||||
GINCOMPLETE = 1<<2,
|
||||
};
|
||||
enum
|
||||
{
|
||||
BCHAR = 1L<<TCHAR,
|
||||
BUCHAR = 1L<<TUCHAR,
|
||||
BSHORT = 1L<<TSHORT,
|
||||
BUSHORT = 1L<<TUSHORT,
|
||||
BINT = 1L<<TINT,
|
||||
BUINT = 1L<<TUINT,
|
||||
BLONG = 1L<<TLONG,
|
||||
BULONG = 1L<<TULONG,
|
||||
BVLONG = 1L<<TVLONG,
|
||||
BUVLONG = 1L<<TUVLONG,
|
||||
BFLOAT = 1L<<TFLOAT,
|
||||
BDOUBLE = 1L<<TDOUBLE,
|
||||
BIND = 1L<<TIND,
|
||||
BFUNC = 1L<<TFUNC,
|
||||
BARRAY = 1L<<TARRAY,
|
||||
BVOID = 1L<<TVOID,
|
||||
BSTRUCT = 1L<<TSTRUCT,
|
||||
BUNION = 1L<<TUNION,
|
||||
BENUM = 1L<<TENUM,
|
||||
BFILE = 1L<<TFILE,
|
||||
BDOT = 1L<<TDOT,
|
||||
BCONSTNT = 1L<<TCONSTNT,
|
||||
BVOLATILE = 1L<<TVOLATILE,
|
||||
BUNSIGNED = 1L<<TUNSIGNED,
|
||||
BSIGNED = 1L<<TSIGNED,
|
||||
BAUTO = 1L<<TAUTO,
|
||||
BEXTERN = 1L<<TEXTERN,
|
||||
BSTATIC = 1L<<TSTATIC,
|
||||
BTYPEDEF = 1L<<TTYPEDEF,
|
||||
BTYPESTR = 1L<<TTYPESTR,
|
||||
BREGISTER = 1L<<TREGISTER,
|
||||
|
||||
BINTEGER = BCHAR|BUCHAR|BSHORT|BUSHORT|BINT|BUINT|
|
||||
BLONG|BULONG|BVLONG|BUVLONG,
|
||||
BNUMBER = BINTEGER|BFLOAT|BDOUBLE,
|
||||
|
||||
/* these can be overloaded with complex types */
|
||||
|
||||
BCLASS = BAUTO|BEXTERN|BSTATIC|BTYPEDEF|BTYPESTR|BREGISTER,
|
||||
BGARB = BCONSTNT|BVOLATILE,
|
||||
};
|
||||
|
||||
struct Funct
|
||||
{
|
||||
Sym* sym[OEND];
|
||||
Sym* castto[NTYPE];
|
||||
Sym* castfr[NTYPE];
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Type* tenum; /* type of entire enum */
|
||||
Type* cenum; /* type of current enum run */
|
||||
vlong lastenum; /* value of current enum */
|
||||
double floatenum; /* value of current enum */
|
||||
} en;
|
||||
|
||||
EXTERN int autobn;
|
||||
EXTERN int32 autoffset;
|
||||
EXTERN int blockno;
|
||||
EXTERN Decl* dclstack;
|
||||
EXTERN int debug[256];
|
||||
EXTERN int32 firstbit;
|
||||
EXTERN Sym* firstarg;
|
||||
EXTERN Type* firstargtype;
|
||||
EXTERN Decl* firstdcl;
|
||||
EXTERN int fperror;
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN char* hunk;
|
||||
EXTERN char** include;
|
||||
EXTERN Io* iofree;
|
||||
EXTERN Io* ionext;
|
||||
EXTERN Io* iostack;
|
||||
EXTERN int32 lastbit;
|
||||
EXTERN char lastclass;
|
||||
EXTERN Type* lastdcl;
|
||||
EXTERN int32 lastfield;
|
||||
EXTERN Type* lasttype;
|
||||
EXTERN int32 lineno;
|
||||
EXTERN int32 nearln;
|
||||
EXTERN int nerrors;
|
||||
EXTERN int newflag;
|
||||
EXTERN int32 nhunk;
|
||||
EXTERN int ninclude;
|
||||
EXTERN Node* nodproto;
|
||||
EXTERN Node* nodcast;
|
||||
EXTERN int32 nsymb;
|
||||
EXTERN Biobuf outbuf;
|
||||
EXTERN Biobuf diagbuf;
|
||||
EXTERN char* outfile;
|
||||
EXTERN int peekc;
|
||||
EXTERN int32 stkoff;
|
||||
EXTERN Type* strf;
|
||||
EXTERN Type* strl;
|
||||
EXTERN char* symb;
|
||||
EXTERN Sym* symstring;
|
||||
EXTERN int taggen;
|
||||
EXTERN Type* tfield;
|
||||
EXTERN Type* tufield;
|
||||
extern int thechar;
|
||||
extern char* thestring;
|
||||
extern LinkArch* thelinkarch;
|
||||
EXTERN Type* thisfn;
|
||||
EXTERN int32 thunk;
|
||||
EXTERN Type* types[NALLTYPES];
|
||||
EXTERN Type* fntypes[NALLTYPES];
|
||||
EXTERN Node* initlist;
|
||||
EXTERN Term term[NTERM];
|
||||
EXTERN int nterm;
|
||||
EXTERN int packflg;
|
||||
EXTERN int fproundflg;
|
||||
EXTERN int textflag;
|
||||
EXTERN int dataflag;
|
||||
EXTERN int flag_largemodel;
|
||||
EXTERN int ncontin;
|
||||
EXTERN int canreach;
|
||||
EXTERN int warnreach;
|
||||
EXTERN int nacl;
|
||||
EXTERN Bits zbits;
|
||||
EXTERN Fmt pragcgobuf;
|
||||
EXTERN Biobuf bstdout;
|
||||
EXTERN Var var[NVAR];
|
||||
|
||||
extern char *onames[], *tnames[], *gnames[];
|
||||
extern char *cnames[], *qnames[], *bnames[];
|
||||
extern uchar tab[NTYPE][NTYPE];
|
||||
extern uchar comrel[], invrel[], logrel[];
|
||||
extern int32 ncast[], tadd[], tand[];
|
||||
extern int32 targ[], tasadd[], tasign[], tcast[];
|
||||
extern int32 tdot[], tfunct[], tindir[], tmul[];
|
||||
extern int32 tnot[], trel[], tsub[];
|
||||
|
||||
extern uchar typeaf[];
|
||||
extern uchar typefd[];
|
||||
extern uchar typei[];
|
||||
extern uchar typesu[];
|
||||
extern uchar typesuv[];
|
||||
extern uchar typeu[];
|
||||
extern uchar typev[];
|
||||
extern uchar typec[];
|
||||
extern uchar typeh[];
|
||||
extern uchar typeil[];
|
||||
extern uchar typeilp[];
|
||||
extern uchar typechl[];
|
||||
extern uchar typechlv[];
|
||||
extern uchar typechlvp[];
|
||||
extern uchar typechlp[];
|
||||
extern uchar typechlpfd[];
|
||||
|
||||
EXTERN uchar* typeword;
|
||||
EXTERN uchar* typecmplx;
|
||||
EXTERN Link* ctxt;
|
||||
|
||||
extern uint32 thash1;
|
||||
extern uint32 thash2;
|
||||
extern uint32 thash3;
|
||||
extern uint32 thash[];
|
||||
|
||||
/*
|
||||
* compat.c/unix.c/windows.c
|
||||
*/
|
||||
int systemtype(int);
|
||||
int pathchar(void);
|
||||
|
||||
/*
|
||||
* parser
|
||||
*/
|
||||
int yyparse(void);
|
||||
int mpatov(char*, vlong*);
|
||||
|
||||
/*
|
||||
* lex.c
|
||||
*/
|
||||
void* allocn(void*, int32, int32);
|
||||
void* alloc(int32);
|
||||
void ensuresymb(int32);
|
||||
void cinit(void);
|
||||
int compile(char*, char**, int);
|
||||
void errorexit(void);
|
||||
int filbuf(void);
|
||||
int getc(void);
|
||||
int32 getr(void);
|
||||
int getnsc(void);
|
||||
Sym* lookup(void);
|
||||
void main(int, char*[]);
|
||||
void newfile(char*, int);
|
||||
void newio(void);
|
||||
void pushio(void);
|
||||
int32 escchar(int32, int, int);
|
||||
Sym* slookup(char*);
|
||||
void syminit(Sym*);
|
||||
void unget(int);
|
||||
int32 yylex(void);
|
||||
int Lconv(Fmt*);
|
||||
int Tconv(Fmt*);
|
||||
int FNconv(Fmt*);
|
||||
int Oconv(Fmt*);
|
||||
int Qconv(Fmt*);
|
||||
int VBconv(Fmt*);
|
||||
int Bconv(Fmt*);
|
||||
void setinclude(char*);
|
||||
|
||||
/*
|
||||
* mac.c
|
||||
*/
|
||||
void dodefine(char*);
|
||||
void domacro(void);
|
||||
Sym* getsym(void);
|
||||
int32 getnsn(void);
|
||||
void macdef(void);
|
||||
void macprag(void);
|
||||
void macend(void);
|
||||
void macexpand(Sym*, char*);
|
||||
void macif(int);
|
||||
void macinc(void);
|
||||
void maclin(void);
|
||||
void macund(void);
|
||||
|
||||
/*
|
||||
* dcl.c
|
||||
*/
|
||||
Node* doinit(Sym*, Type*, int32, Node*);
|
||||
Type* tcopy(Type*);
|
||||
Node* init1(Sym*, Type*, int32, int);
|
||||
Node* newlist(Node*, Node*);
|
||||
void adecl(int, Type*, Sym*);
|
||||
int anyproto(Node*);
|
||||
void argmark(Node*, int);
|
||||
void dbgdecl(Sym*);
|
||||
Node* dcllabel(Sym*, int);
|
||||
Node* dodecl(void(*)(int, Type*, Sym*), int, Type*, Node*);
|
||||
Sym* mkstatic(Sym*);
|
||||
void doenum(Sym*, Node*);
|
||||
void snap(Type*);
|
||||
Type* dotag(Sym*, int, int);
|
||||
void edecl(int, Type*, Sym*);
|
||||
Type* fnproto(Node*);
|
||||
Type* fnproto1(Node*);
|
||||
void markdcl(void);
|
||||
Type* paramconv(Type*, int);
|
||||
void pdecl(int, Type*, Sym*);
|
||||
Decl* push(void);
|
||||
Decl* push1(Sym*);
|
||||
Node* revertdcl(void);
|
||||
int32 xround(int32, int);
|
||||
int rsametype(Type*, Type*, int, int);
|
||||
int sametype(Type*, Type*);
|
||||
uint32 sign(Sym*);
|
||||
uint32 signature(Type*);
|
||||
void sualign(Type*);
|
||||
void tmerge(Type*, Sym*);
|
||||
void walkparam(Node*, int);
|
||||
void xdecl(int, Type*, Sym*);
|
||||
Node* contig(Sym*, Node*, int32);
|
||||
|
||||
/*
|
||||
* com.c
|
||||
*/
|
||||
void ccom(Node*);
|
||||
void complex(Node*);
|
||||
int tcom(Node*);
|
||||
int tcoma(Node*, Node*, Type*, int);
|
||||
int tcomd(Node*);
|
||||
int tcomo(Node*, int);
|
||||
int tcomx(Node*);
|
||||
int tlvalue(Node*);
|
||||
void constas(Node*, Type*, Type*);
|
||||
|
||||
/*
|
||||
* con.c
|
||||
*/
|
||||
void acom(Node*);
|
||||
void acom1(vlong, Node*);
|
||||
void acom2(Node*, Type*);
|
||||
int acomcmp1(const void*, const void*);
|
||||
int acomcmp2(const void*, const void*);
|
||||
int addo(Node*);
|
||||
void evconst(Node*);
|
||||
|
||||
/*
|
||||
* funct.c
|
||||
*/
|
||||
int isfunct(Node*);
|
||||
void dclfunct(Type*, Sym*);
|
||||
|
||||
/*
|
||||
* sub.c
|
||||
*/
|
||||
void arith(Node*, int);
|
||||
int deadheads(Node*);
|
||||
Type* dotsearch(Sym*, Type*, Node*, int32*);
|
||||
int32 dotoffset(Type*, Type*, Node*);
|
||||
void gethunk(void);
|
||||
Node* invert(Node*);
|
||||
int bitno(int32);
|
||||
void makedot(Node*, Type*, int32);
|
||||
int mixedasop(Type*, Type*);
|
||||
Node* new(int, Node*, Node*);
|
||||
Node* new1(int, Node*, Node*);
|
||||
int nilcast(Type*, Type*);
|
||||
int nocast(Type*, Type*);
|
||||
void prtree(Node*, char*);
|
||||
void prtree1(Node*, int, int);
|
||||
void relcon(Node*, Node*);
|
||||
int relindex(int);
|
||||
int simpleg(int32);
|
||||
Type* garbt(Type*, int32);
|
||||
int simplec(int32);
|
||||
Type* simplet(int32);
|
||||
int stcompat(Node*, Type*, Type*, int32[]);
|
||||
int tcompat(Node*, Type*, Type*, int32[]);
|
||||
void tinit(void);
|
||||
Type* typ(int, Type*);
|
||||
Type* copytyp(Type*);
|
||||
void typeext(Type*, Node*);
|
||||
void typeext1(Type*, Node*);
|
||||
int side(Node*);
|
||||
int vconst(Node*);
|
||||
int xlog2(uvlong);
|
||||
int vlog(Node*);
|
||||
int topbit(uint32);
|
||||
void simplifyshift(Node*);
|
||||
int32 typebitor(int32, int32);
|
||||
void diag(Node*, char*, ...);
|
||||
void warn(Node*, char*, ...);
|
||||
void yyerror(char*, ...);
|
||||
void fatal(Node*, char*, ...);
|
||||
LSym* linksym(Sym*);
|
||||
|
||||
/*
|
||||
* acid.c
|
||||
*/
|
||||
void acidtype(Type*);
|
||||
void acidvar(Sym*);
|
||||
|
||||
/*
|
||||
* godefs.c
|
||||
*/
|
||||
int Uconv(Fmt*);
|
||||
void godeftype(Type*);
|
||||
void godefvar(Sym*);
|
||||
|
||||
/*
|
||||
* bits.c
|
||||
*/
|
||||
Bits bor(Bits, Bits);
|
||||
Bits band(Bits, Bits);
|
||||
Bits bnot(Bits);
|
||||
int bany(Bits*);
|
||||
int bnum(Bits);
|
||||
Bits blsh(uint);
|
||||
int beq(Bits, Bits);
|
||||
int bset(Bits, uint);
|
||||
|
||||
/*
|
||||
* dpchk.c
|
||||
*/
|
||||
void dpcheck(Node*);
|
||||
void arginit(void);
|
||||
void pragvararg(void);
|
||||
void pragpack(void);
|
||||
void pragfpround(void);
|
||||
void pragdataflag(void);
|
||||
void pragtextflag(void);
|
||||
void pragincomplete(void);
|
||||
void pragcgo(char*);
|
||||
|
||||
/*
|
||||
* calls to machine depend part
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gclean(void);
|
||||
void gextern(Sym*, Node*, int32, int32);
|
||||
void ginit(void);
|
||||
int32 outstring(char*, int32);
|
||||
int32 outlstring(TRune*, int32);
|
||||
void sextern(Sym*, Node*, int32, int32);
|
||||
void xcom(Node*);
|
||||
int32 exreg(Type*);
|
||||
int32 align(int32, Type*, int, int32*);
|
||||
int32 maxround(int32, int32);
|
||||
int hasdotdotdot(Type*);
|
||||
void linkarchinit(void);
|
||||
|
||||
extern schar ewidth[];
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
double convvtof(vlong);
|
||||
vlong convftov(double);
|
||||
double convftox(double, int);
|
||||
vlong convvtox(vlong, int);
|
||||
|
||||
/*
|
||||
* machcap
|
||||
*/
|
||||
int machcap(Node*);
|
||||
|
||||
#pragma varargck argpos warn 2
|
||||
#pragma varargck argpos diag 2
|
||||
#pragma varargck argpos yyerror 1
|
||||
|
||||
#pragma varargck type "B" Bits
|
||||
#pragma varargck type "F" Node*
|
||||
#pragma varargck type "L" int32
|
||||
#pragma varargck type "Q" int32
|
||||
#pragma varargck type "O" int
|
||||
#pragma varargck type "O" uint
|
||||
#pragma varargck type "T" Type*
|
||||
#pragma varargck type "U" char*
|
||||
#pragma varargck type "|" int
|
||||
|
||||
enum
|
||||
{
|
||||
Plan9 = 1<<0,
|
||||
Unix = 1<<1,
|
||||
Windows = 1<<2,
|
||||
};
|
||||
int pathchar(void);
|
||||
int systemtype(int);
|
||||
void* alloc(int32 n);
|
||||
void* allocn(void*, int32, int32);
|
1220
src/cmd/cc/cc.y
1220
src/cmd/cc/cc.y
File diff suppressed because it is too large
Load Diff
1384
src/cmd/cc/com.c
1384
src/cmd/cc/com.c
File diff suppressed because it is too large
Load Diff
@ -1,644 +0,0 @@
|
||||
// Inferno utils/cc/com64.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/com64.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 "cc.h"
|
||||
|
||||
/*
|
||||
* this is machine depend, but it is totally
|
||||
* common on all of the 64-bit symulating machines.
|
||||
*/
|
||||
|
||||
#define FNX 100 /* botch -- redefinition */
|
||||
|
||||
Node* nodaddv;
|
||||
Node* nodsubv;
|
||||
Node* nodmulv;
|
||||
Node* noddivv;
|
||||
Node* noddivvu;
|
||||
Node* nodmodv;
|
||||
Node* nodmodvu;
|
||||
Node* nodlshv;
|
||||
Node* nodrshav;
|
||||
Node* nodrshlv;
|
||||
Node* nodandv;
|
||||
Node* nodorv;
|
||||
Node* nodxorv;
|
||||
Node* nodnegv;
|
||||
Node* nodcomv;
|
||||
|
||||
Node* nodtestv;
|
||||
Node* nodeqv;
|
||||
Node* nodnev;
|
||||
Node* nodlev;
|
||||
Node* nodltv;
|
||||
Node* nodgev;
|
||||
Node* nodgtv;
|
||||
Node* nodhiv;
|
||||
Node* nodhsv;
|
||||
Node* nodlov;
|
||||
Node* nodlsv;
|
||||
|
||||
Node* nodf2v;
|
||||
Node* nodd2v;
|
||||
Node* nodp2v;
|
||||
Node* nodsi2v;
|
||||
Node* nodui2v;
|
||||
Node* nodsl2v;
|
||||
Node* nodul2v;
|
||||
Node* nodsh2v;
|
||||
Node* noduh2v;
|
||||
Node* nodsc2v;
|
||||
Node* noduc2v;
|
||||
|
||||
Node* nodv2f;
|
||||
Node* nodv2d;
|
||||
Node* nodv2ui;
|
||||
Node* nodv2si;
|
||||
Node* nodv2ul;
|
||||
Node* nodv2sl;
|
||||
Node* nodv2uh;
|
||||
Node* nodv2sh;
|
||||
Node* nodv2uc;
|
||||
Node* nodv2sc;
|
||||
|
||||
Node* nodvpp;
|
||||
Node* nodppv;
|
||||
Node* nodvmm;
|
||||
Node* nodmmv;
|
||||
|
||||
Node* nodvasop;
|
||||
|
||||
char etconv[NALLTYPES]; /* for _vasop */
|
||||
Init initetconv[] =
|
||||
{
|
||||
TCHAR, 1, 0,
|
||||
TUCHAR, 2, 0,
|
||||
TSHORT, 3, 0,
|
||||
TUSHORT, 4, 0,
|
||||
TLONG, 5, 0,
|
||||
TULONG, 6, 0,
|
||||
TVLONG, 7, 0,
|
||||
TUVLONG, 8, 0,
|
||||
TINT, 9, 0,
|
||||
TUINT, 10, 0,
|
||||
-1, 0, 0,
|
||||
};
|
||||
|
||||
Node*
|
||||
fvn(char *name, int type)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(name);
|
||||
n->sym->sig = SIGINTERN;
|
||||
if(fntypes[type] == 0)
|
||||
fntypes[type] = typ(TFUNC, types[type]);
|
||||
n->type = fntypes[type];
|
||||
n->etype = type;
|
||||
n->class = CGLOBL;
|
||||
n->addable = 10;
|
||||
n->complex = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
com64init(void)
|
||||
{
|
||||
Init *p;
|
||||
|
||||
nodaddv = fvn("_addv", TVLONG);
|
||||
nodsubv = fvn("_subv", TVLONG);
|
||||
nodmulv = fvn("_mulv", TVLONG);
|
||||
noddivv = fvn("_divv", TVLONG);
|
||||
noddivvu = fvn("_divvu", TVLONG);
|
||||
nodmodv = fvn("_modv", TVLONG);
|
||||
nodmodvu = fvn("_modvu", TVLONG);
|
||||
nodlshv = fvn("_lshv", TVLONG);
|
||||
nodrshav = fvn("_rshav", TVLONG);
|
||||
nodrshlv = fvn("_rshlv", TVLONG);
|
||||
nodandv = fvn("_andv", TVLONG);
|
||||
nodorv = fvn("_orv", TVLONG);
|
||||
nodxorv = fvn("_xorv", TVLONG);
|
||||
nodnegv = fvn("_negv", TVLONG);
|
||||
nodcomv = fvn("_comv", TVLONG);
|
||||
|
||||
nodtestv = fvn("_testv", TLONG);
|
||||
nodeqv = fvn("_eqv", TLONG);
|
||||
nodnev = fvn("_nev", TLONG);
|
||||
nodlev = fvn("_lev", TLONG);
|
||||
nodltv = fvn("_ltv", TLONG);
|
||||
nodgev = fvn("_gev", TLONG);
|
||||
nodgtv = fvn("_gtv", TLONG);
|
||||
nodhiv = fvn("_hiv", TLONG);
|
||||
nodhsv = fvn("_hsv", TLONG);
|
||||
nodlov = fvn("_lov", TLONG);
|
||||
nodlsv = fvn("_lsv", TLONG);
|
||||
|
||||
nodf2v = fvn("_f2v", TVLONG);
|
||||
nodd2v = fvn("_d2v", TVLONG);
|
||||
nodp2v = fvn("_p2v", TVLONG);
|
||||
nodsi2v = fvn("_si2v", TVLONG);
|
||||
nodui2v = fvn("_ui2v", TVLONG);
|
||||
nodsl2v = fvn("_sl2v", TVLONG);
|
||||
nodul2v = fvn("_ul2v", TVLONG);
|
||||
nodsh2v = fvn("_sh2v", TVLONG);
|
||||
noduh2v = fvn("_uh2v", TVLONG);
|
||||
nodsc2v = fvn("_sc2v", TVLONG);
|
||||
noduc2v = fvn("_uc2v", TVLONG);
|
||||
|
||||
nodv2f = fvn("_v2f", TFLOAT);
|
||||
nodv2d = fvn("_v2d", TDOUBLE);
|
||||
nodv2sl = fvn("_v2sl", TLONG);
|
||||
nodv2ul = fvn("_v2ul", TULONG);
|
||||
nodv2si = fvn("_v2si", TINT);
|
||||
nodv2ui = fvn("_v2ui", TUINT);
|
||||
nodv2sh = fvn("_v2sh", TSHORT);
|
||||
nodv2uh = fvn("_v2ul", TUSHORT);
|
||||
nodv2sc = fvn("_v2sc", TCHAR);
|
||||
nodv2uc = fvn("_v2uc", TUCHAR);
|
||||
|
||||
nodvpp = fvn("_vpp", TVLONG);
|
||||
nodppv = fvn("_ppv", TVLONG);
|
||||
nodvmm = fvn("_vmm", TVLONG);
|
||||
nodmmv = fvn("_mmv", TVLONG);
|
||||
|
||||
nodvasop = fvn("_vasop", TVLONG);
|
||||
|
||||
for(p = initetconv; p->code >= 0; p++)
|
||||
etconv[p->code] = p->value;
|
||||
}
|
||||
|
||||
int
|
||||
com64(Node *n)
|
||||
{
|
||||
Node *l, *r, *a, *t;
|
||||
int lv, rv;
|
||||
|
||||
if(n->type == 0)
|
||||
return 0;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
|
||||
lv = 0;
|
||||
if(l && l->type && typev[l->type->etype])
|
||||
lv = 1;
|
||||
rv = 0;
|
||||
if(r && r->type && typev[r->type->etype])
|
||||
rv = 1;
|
||||
|
||||
if(lv) {
|
||||
switch(n->op) {
|
||||
case OEQ:
|
||||
a = nodeqv;
|
||||
goto setbool;
|
||||
case ONE:
|
||||
a = nodnev;
|
||||
goto setbool;
|
||||
case OLE:
|
||||
a = nodlev;
|
||||
goto setbool;
|
||||
case OLT:
|
||||
a = nodltv;
|
||||
goto setbool;
|
||||
case OGE:
|
||||
a = nodgev;
|
||||
goto setbool;
|
||||
case OGT:
|
||||
a = nodgtv;
|
||||
goto setbool;
|
||||
case OHI:
|
||||
a = nodhiv;
|
||||
goto setbool;
|
||||
case OHS:
|
||||
a = nodhsv;
|
||||
goto setbool;
|
||||
case OLO:
|
||||
a = nodlov;
|
||||
goto setbool;
|
||||
case OLS:
|
||||
a = nodlsv;
|
||||
goto setbool;
|
||||
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
|
||||
if(rv) {
|
||||
r = new(OFUNC, nodtestv, r);
|
||||
n->right = r;
|
||||
r->complex = FNX;
|
||||
r->op = OFUNC;
|
||||
r->type = types[TLONG];
|
||||
}
|
||||
|
||||
case OCOND:
|
||||
case ONOT:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
|
||||
l = new(OFUNC, nodtestv, l);
|
||||
n->left = l;
|
||||
l->complex = FNX;
|
||||
l->op = OFUNC;
|
||||
l->type = types[TLONG];
|
||||
n->complex = FNX;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(rv) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->op) {
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
r = new(OFUNC, nodtestv, r);
|
||||
n->right = r;
|
||||
r->complex = FNX;
|
||||
r->op = OFUNC;
|
||||
r->type = types[TLONG];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(typev[n->type->etype]) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->op) {
|
||||
default:
|
||||
diag(n, "unknown vlong %O", n->op);
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
case ORETURN:
|
||||
case OAS:
|
||||
case OIND:
|
||||
return 1;
|
||||
case OADD:
|
||||
a = nodaddv;
|
||||
goto setbop;
|
||||
case OSUB:
|
||||
a = nodsubv;
|
||||
goto setbop;
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
a = nodmulv;
|
||||
goto setbop;
|
||||
case ODIV:
|
||||
a = noddivv;
|
||||
goto setbop;
|
||||
case OLDIV:
|
||||
a = noddivvu;
|
||||
goto setbop;
|
||||
case OMOD:
|
||||
a = nodmodv;
|
||||
goto setbop;
|
||||
case OLMOD:
|
||||
a = nodmodvu;
|
||||
goto setbop;
|
||||
case OASHL:
|
||||
a = nodlshv;
|
||||
goto setbop;
|
||||
case OASHR:
|
||||
a = nodrshav;
|
||||
goto setbop;
|
||||
case OLSHR:
|
||||
a = nodrshlv;
|
||||
goto setbop;
|
||||
case OAND:
|
||||
a = nodandv;
|
||||
goto setbop;
|
||||
case OOR:
|
||||
a = nodorv;
|
||||
goto setbop;
|
||||
case OXOR:
|
||||
a = nodxorv;
|
||||
goto setbop;
|
||||
case OPOSTINC:
|
||||
a = nodvpp;
|
||||
goto setvinc;
|
||||
case OPOSTDEC:
|
||||
a = nodvmm;
|
||||
goto setvinc;
|
||||
case OPREINC:
|
||||
a = nodppv;
|
||||
goto setvinc;
|
||||
case OPREDEC:
|
||||
a = nodmmv;
|
||||
goto setvinc;
|
||||
case ONEG:
|
||||
a = nodnegv;
|
||||
goto setfnx;
|
||||
case OCOM:
|
||||
a = nodcomv;
|
||||
goto setfnx;
|
||||
case OCAST:
|
||||
switch(l->type->etype) {
|
||||
case TCHAR:
|
||||
a = nodsc2v;
|
||||
goto setfnxl;
|
||||
case TUCHAR:
|
||||
a = noduc2v;
|
||||
goto setfnxl;
|
||||
case TSHORT:
|
||||
a = nodsh2v;
|
||||
goto setfnxl;
|
||||
case TUSHORT:
|
||||
a = noduh2v;
|
||||
goto setfnxl;
|
||||
case TINT:
|
||||
a = nodsi2v;
|
||||
goto setfnx;
|
||||
case TUINT:
|
||||
a = nodui2v;
|
||||
goto setfnx;
|
||||
case TLONG:
|
||||
a = nodsl2v;
|
||||
goto setfnx;
|
||||
case TULONG:
|
||||
a = nodul2v;
|
||||
goto setfnx;
|
||||
case TFLOAT:
|
||||
a = nodf2v;
|
||||
goto setfnx;
|
||||
case TDOUBLE:
|
||||
a = nodd2v;
|
||||
goto setfnx;
|
||||
case TIND:
|
||||
a = nodp2v;
|
||||
goto setfnx;
|
||||
}
|
||||
diag(n, "unknown %T->vlong cast", l->type);
|
||||
return 1;
|
||||
case OASADD:
|
||||
a = nodaddv;
|
||||
goto setasop;
|
||||
case OASSUB:
|
||||
a = nodsubv;
|
||||
goto setasop;
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
a = nodmulv;
|
||||
goto setasop;
|
||||
case OASDIV:
|
||||
a = noddivv;
|
||||
goto setasop;
|
||||
case OASLDIV:
|
||||
a = noddivvu;
|
||||
goto setasop;
|
||||
case OASMOD:
|
||||
a = nodmodv;
|
||||
goto setasop;
|
||||
case OASLMOD:
|
||||
a = nodmodvu;
|
||||
goto setasop;
|
||||
case OASASHL:
|
||||
a = nodlshv;
|
||||
goto setasop;
|
||||
case OASASHR:
|
||||
a = nodrshav;
|
||||
goto setasop;
|
||||
case OASLSHR:
|
||||
a = nodrshlv;
|
||||
goto setasop;
|
||||
case OASAND:
|
||||
a = nodandv;
|
||||
goto setasop;
|
||||
case OASOR:
|
||||
a = nodorv;
|
||||
goto setasop;
|
||||
case OASXOR:
|
||||
a = nodxorv;
|
||||
goto setasop;
|
||||
}
|
||||
}
|
||||
|
||||
if(typefd[n->type->etype] && l && l->op == OFUNC) {
|
||||
switch(n->op) {
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASMOD:
|
||||
case OASLMOD:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
if(l->right && typev[l->right->etype]) {
|
||||
diag(n, "sorry float <asop> vlong not implemented\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(n->op == OCAST) {
|
||||
if(l->type && typev[l->type->etype]) {
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
switch(n->type->etype) {
|
||||
case TDOUBLE:
|
||||
a = nodv2d;
|
||||
goto setfnx;
|
||||
case TFLOAT:
|
||||
a = nodv2f;
|
||||
goto setfnx;
|
||||
case TLONG:
|
||||
a = nodv2sl;
|
||||
goto setfnx;
|
||||
case TULONG:
|
||||
a = nodv2ul;
|
||||
goto setfnx;
|
||||
case TINT:
|
||||
a = nodv2si;
|
||||
goto setfnx;
|
||||
case TUINT:
|
||||
a = nodv2ui;
|
||||
goto setfnx;
|
||||
case TSHORT:
|
||||
a = nodv2sh;
|
||||
goto setfnx;
|
||||
case TUSHORT:
|
||||
a = nodv2uh;
|
||||
goto setfnx;
|
||||
case TCHAR:
|
||||
a = nodv2sc;
|
||||
goto setfnx;
|
||||
case TUCHAR:
|
||||
a = nodv2uc;
|
||||
goto setfnx;
|
||||
case TIND: // small pun here
|
||||
a = nodv2ul;
|
||||
goto setfnx;
|
||||
}
|
||||
diag(n, "unknown vlong->%T cast", n->type);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
setbop:
|
||||
n->left = a;
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setfnxl:
|
||||
l = new(OCAST, l, 0);
|
||||
l->type = types[TLONG];
|
||||
l->complex = l->left->complex;
|
||||
|
||||
setfnx:
|
||||
n->left = a;
|
||||
n->right = l;
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setvinc:
|
||||
n->left = a;
|
||||
l = new(OADDR, l, Z);
|
||||
l->type = typ(TIND, l->left->type);
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
return 1;
|
||||
|
||||
setbool:
|
||||
if(machcap(n))
|
||||
return 1;
|
||||
n->left = a;
|
||||
n->right = new(OLIST, l, r);
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
n->type = types[TLONG];
|
||||
return 1;
|
||||
|
||||
setasop:
|
||||
if(l->op == OFUNC) {
|
||||
l = l->right;
|
||||
goto setasop;
|
||||
}
|
||||
|
||||
t = new(OCONST, 0, 0);
|
||||
t->vconst = etconv[l->type->etype];
|
||||
t->type = types[TLONG];
|
||||
t->addable = 20;
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
t = new(OADDR, a, 0);
|
||||
t->type = typ(TIND, a->type);
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
t = new(OADDR, l, 0);
|
||||
t->type = typ(TIND, l->type);
|
||||
r = new(OLIST, t, r);
|
||||
|
||||
n->left = nodvasop;
|
||||
n->right = r;
|
||||
n->complex = FNX;
|
||||
n->op = OFUNC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
bool64(Node *n)
|
||||
{
|
||||
Node *n1;
|
||||
|
||||
if(machcap(Z))
|
||||
return;
|
||||
if(typev[n->type->etype]) {
|
||||
n1 = new(OXXX, 0, 0);
|
||||
*n1 = *n;
|
||||
|
||||
n->right = n1;
|
||||
n->left = nodtestv;
|
||||
n->complex = FNX;
|
||||
n->addable = 0;
|
||||
n->op = OFUNC;
|
||||
n->type = types[TLONG];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* more machine depend stuff.
|
||||
* this is common for 8,16,32,64 bit machines.
|
||||
* this is common for ieee machines.
|
||||
*/
|
||||
double
|
||||
convvtof(vlong v)
|
||||
{
|
||||
double d;
|
||||
|
||||
d = v; /* BOTCH */
|
||||
return d;
|
||||
}
|
||||
|
||||
vlong
|
||||
convftov(double d)
|
||||
{
|
||||
vlong v;
|
||||
|
||||
|
||||
v = d; /* BOTCH */
|
||||
return v;
|
||||
}
|
||||
|
||||
double
|
||||
convftox(double d, int et)
|
||||
{
|
||||
|
||||
if(!typefd[et])
|
||||
diag(Z, "bad type in castftox %s", tnames[et]);
|
||||
return d;
|
||||
}
|
||||
|
||||
vlong
|
||||
convvtox(vlong c, int et)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 8 * ewidth[et];
|
||||
c &= MASK(n);
|
||||
if(!typeu[et])
|
||||
if(c & SIGN(n))
|
||||
c |= ~MASK(n);
|
||||
return c;
|
||||
}
|
1707
src/cmd/cc/dcl.c
1707
src/cmd/cc/dcl.c
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
|
||||
This directory contains the portable section of the Plan 9 C compilers.
|
||||
See ../6c, ../8c, and ../5c for more information.
|
||||
|
||||
*/
|
||||
package main
|
@ -1,793 +0,0 @@
|
||||
// Inferno utils/cc/dpchk.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/dpchk.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 "cc.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Fnone = 0,
|
||||
Fl,
|
||||
Fvl,
|
||||
Fignor,
|
||||
Fstar,
|
||||
Fadj,
|
||||
|
||||
Fverb = 10,
|
||||
};
|
||||
|
||||
typedef struct Tprot Tprot;
|
||||
struct Tprot
|
||||
{
|
||||
Type* type;
|
||||
Bits flag;
|
||||
Tprot* link;
|
||||
};
|
||||
|
||||
typedef struct Tname Tname;
|
||||
struct Tname
|
||||
{
|
||||
char* name;
|
||||
int param;
|
||||
int count;
|
||||
Tname* link;
|
||||
Tprot* prot;
|
||||
};
|
||||
|
||||
static Type* indchar;
|
||||
static uchar flagbits[512];
|
||||
static char* lastfmt;
|
||||
static int lastadj;
|
||||
static int lastverb;
|
||||
static int nstar;
|
||||
static Tprot* tprot;
|
||||
static Tname* tname;
|
||||
|
||||
void
|
||||
argflag(int c, int v)
|
||||
{
|
||||
|
||||
switch(v) {
|
||||
case Fignor:
|
||||
case Fstar:
|
||||
case Fl:
|
||||
case Fvl:
|
||||
flagbits[c] = v;
|
||||
break;
|
||||
case Fverb:
|
||||
flagbits[c] = lastverb;
|
||||
/*print("flag-v %c %d\n", c, lastadj);*/
|
||||
lastverb++;
|
||||
break;
|
||||
case Fadj:
|
||||
flagbits[c] = lastadj;
|
||||
/*print("flag-l %c %d\n", c, lastadj);*/
|
||||
lastadj++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Bits
|
||||
getflag(char *s)
|
||||
{
|
||||
Bits flag;
|
||||
int f;
|
||||
Fmt fmt;
|
||||
Rune c;
|
||||
|
||||
flag = zbits;
|
||||
nstar = 0;
|
||||
fmtstrinit(&fmt);
|
||||
for(;;) {
|
||||
s += chartorune(&c, s);
|
||||
if(c == 0 || c >= nelem(flagbits))
|
||||
break;
|
||||
fmtrune(&fmt, c);
|
||||
f = flagbits[c];
|
||||
switch(f) {
|
||||
case Fnone:
|
||||
argflag(c, Fverb);
|
||||
f = flagbits[c];
|
||||
break;
|
||||
case Fstar:
|
||||
nstar++;
|
||||
case Fignor:
|
||||
continue;
|
||||
case Fl:
|
||||
if(bset(flag, Fl))
|
||||
flag = bor(flag, blsh(Fvl));
|
||||
}
|
||||
flag = bor(flag, blsh(f));
|
||||
if(f >= Fverb)
|
||||
break;
|
||||
}
|
||||
free(lastfmt);
|
||||
lastfmt = fmtstrflush(&fmt);
|
||||
return flag;
|
||||
}
|
||||
|
||||
static void
|
||||
newprot(Sym *m, Type *t, char *s, Tprot **prot)
|
||||
{
|
||||
Bits flag;
|
||||
Tprot *l;
|
||||
|
||||
if(t == T) {
|
||||
warn(Z, "%s: newprot: type not defined", m->name);
|
||||
return;
|
||||
}
|
||||
flag = getflag(s);
|
||||
for(l=*prot; l; l=l->link)
|
||||
if(beq(flag, l->flag) && sametype(t, l->type))
|
||||
return;
|
||||
l = alloc(sizeof(*l));
|
||||
l->type = t;
|
||||
l->flag = flag;
|
||||
l->link = *prot;
|
||||
*prot = l;
|
||||
}
|
||||
|
||||
static Tname*
|
||||
newname(char *s, int p, int count)
|
||||
{
|
||||
Tname *l;
|
||||
|
||||
for(l=tname; l; l=l->link)
|
||||
if(strcmp(l->name, s) == 0) {
|
||||
if(p >= 0 && l->param != p)
|
||||
yyerror("vargck %s already defined\n", s);
|
||||
return l;
|
||||
}
|
||||
if(p < 0)
|
||||
return nil;
|
||||
|
||||
l = alloc(sizeof(*l));
|
||||
l->name = s;
|
||||
l->param = p;
|
||||
l->link = tname;
|
||||
l->count = count;
|
||||
tname = l;
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
arginit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* debug['F'] = 1;*/
|
||||
/* debug['w'] = 1;*/
|
||||
|
||||
lastadj = Fadj;
|
||||
lastverb = Fverb;
|
||||
indchar = typ(TIND, types[TCHAR]);
|
||||
|
||||
memset(flagbits, Fnone, sizeof(flagbits));
|
||||
|
||||
for(i='0'; i<='9'; i++)
|
||||
argflag(i, Fignor);
|
||||
argflag('.', Fignor);
|
||||
argflag('#', Fignor);
|
||||
argflag('u', Fignor);
|
||||
argflag('h', Fignor);
|
||||
argflag('+', Fignor);
|
||||
argflag('-', Fignor);
|
||||
|
||||
argflag('*', Fstar);
|
||||
argflag('l', Fl);
|
||||
|
||||
argflag('o', Fverb);
|
||||
flagbits['x'] = flagbits['o'];
|
||||
flagbits['X'] = flagbits['o'];
|
||||
}
|
||||
|
||||
static char*
|
||||
getquoted(void)
|
||||
{
|
||||
int c;
|
||||
Rune r;
|
||||
Fmt fmt;
|
||||
|
||||
c = getnsc();
|
||||
if(c != '"')
|
||||
return nil;
|
||||
fmtstrinit(&fmt);
|
||||
for(;;) {
|
||||
r = getr();
|
||||
if(r == '\n') {
|
||||
free(fmtstrflush(&fmt));
|
||||
return nil;
|
||||
}
|
||||
if(r == '"')
|
||||
break;
|
||||
fmtrune(&fmt, r);
|
||||
}
|
||||
free(lastfmt);
|
||||
lastfmt = fmtstrflush(&fmt);
|
||||
return strdup(lastfmt);
|
||||
}
|
||||
|
||||
void
|
||||
pragvararg(void)
|
||||
{
|
||||
Sym *s;
|
||||
int n, c;
|
||||
char *t;
|
||||
Type *ty;
|
||||
Tname *l;
|
||||
|
||||
if(!debug['F'])
|
||||
goto out;
|
||||
s = getsym();
|
||||
if(s && strcmp(s->name, "argpos") == 0)
|
||||
goto ckpos;
|
||||
if(s && strcmp(s->name, "type") == 0)
|
||||
goto cktype;
|
||||
if(s && strcmp(s->name, "flag") == 0)
|
||||
goto ckflag;
|
||||
if(s && strcmp(s->name, "countpos") == 0)
|
||||
goto ckcount;
|
||||
yyerror("syntax in #pragma varargck");
|
||||
goto out;
|
||||
|
||||
ckpos:
|
||||
/*#pragma varargck argpos warn 2*/
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
n = getnsn();
|
||||
if(n < 0)
|
||||
goto bad;
|
||||
newname(s->name, n, 0);
|
||||
goto out;
|
||||
|
||||
ckcount:
|
||||
/*#pragma varargck countpos name 2*/
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
n = getnsn();
|
||||
if(n < 0)
|
||||
goto bad;
|
||||
newname(s->name, 0, n);
|
||||
goto out;
|
||||
|
||||
ckflag:
|
||||
/*#pragma varargck flag 'c'*/
|
||||
c = getnsc();
|
||||
if(c != '\'')
|
||||
goto bad;
|
||||
c = getr();
|
||||
if(c == '\\')
|
||||
c = getr();
|
||||
else if(c == '\'')
|
||||
goto bad;
|
||||
if(c == '\n')
|
||||
goto bad;
|
||||
if(getc() != '\'')
|
||||
goto bad;
|
||||
argflag(c, Fignor);
|
||||
goto out;
|
||||
|
||||
cktype:
|
||||
c = getnsc();
|
||||
unget(c);
|
||||
if(c != '"') {
|
||||
/*#pragma varargck type name int*/
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
l = newname(s->name, -1, -1);
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
ty = s->type;
|
||||
while((c = getnsc()) == '*')
|
||||
ty = typ(TIND, ty);
|
||||
unget(c);
|
||||
newprot(s, ty, "a", &l->prot);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*#pragma varargck type O int*/
|
||||
t = getquoted();
|
||||
if(t == nil)
|
||||
goto bad;
|
||||
s = getsym();
|
||||
if(s == S)
|
||||
goto bad;
|
||||
ty = s->type;
|
||||
while((c = getnsc()) == '*')
|
||||
ty = typ(TIND, ty);
|
||||
unget(c);
|
||||
newprot(s, ty, t, &tprot);
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
yyerror("syntax in #pragma varargck");
|
||||
|
||||
out:
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
||||
|
||||
Node*
|
||||
nextarg(Node *n, Node **a)
|
||||
{
|
||||
if(n == Z) {
|
||||
*a = Z;
|
||||
return Z;
|
||||
}
|
||||
if(n->op == OLIST) {
|
||||
*a = n->left;
|
||||
return n->right;
|
||||
}
|
||||
*a = n;
|
||||
return Z;
|
||||
}
|
||||
|
||||
void
|
||||
checkargs(Node *nn, char *s, int pos)
|
||||
{
|
||||
Node *a, *n;
|
||||
Bits flag;
|
||||
Tprot *l;
|
||||
|
||||
if(!debug['F'])
|
||||
return;
|
||||
n = nn;
|
||||
for(;;) {
|
||||
s = strchr(s, '%');
|
||||
if(s == 0) {
|
||||
nextarg(n, &a);
|
||||
if(a != Z)
|
||||
warn(nn, "more arguments than format %T",
|
||||
a->type);
|
||||
return;
|
||||
}
|
||||
s++;
|
||||
flag = getflag(s);
|
||||
while(nstar > 0) {
|
||||
n = nextarg(n, &a);
|
||||
pos++;
|
||||
nstar--;
|
||||
if(a == Z) {
|
||||
warn(nn, "more format than arguments %s",
|
||||
lastfmt);
|
||||
return;
|
||||
}
|
||||
if(a->type == T)
|
||||
continue;
|
||||
if(!sametype(types[TINT], a->type) &&
|
||||
!sametype(types[TUINT], a->type))
|
||||
warn(nn, "format mismatch '*' in %s %T, arg %d",
|
||||
lastfmt, a->type, pos);
|
||||
}
|
||||
for(l=tprot; l; l=l->link)
|
||||
if(sametype(types[TVOID], l->type)) {
|
||||
if(beq(flag, l->flag)) {
|
||||
s++;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
n = nextarg(n, &a);
|
||||
pos++;
|
||||
if(a == Z) {
|
||||
warn(nn, "more format than arguments %s",
|
||||
lastfmt);
|
||||
return;
|
||||
}
|
||||
if(a->type == 0)
|
||||
continue;
|
||||
for(l=tprot; l; l=l->link)
|
||||
if(sametype(a->type, l->type)) {
|
||||
/*print("checking %T/%ux %T/%ux\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
|
||||
if(beq(flag, l->flag))
|
||||
goto loop;
|
||||
}
|
||||
warn(nn, "format mismatch %s %T, arg %d", lastfmt, a->type, pos);
|
||||
loop:;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dpcheck(Node *n)
|
||||
{
|
||||
char *s;
|
||||
Node *a, *b;
|
||||
Tname *l;
|
||||
Tprot *tl;
|
||||
int i, j;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
b = n->left;
|
||||
if(b == Z || b->op != ONAME)
|
||||
return;
|
||||
s = b->sym->name;
|
||||
for(l=tname; l; l=l->link)
|
||||
if(strcmp(s, l->name) == 0)
|
||||
break;
|
||||
if(l == 0)
|
||||
return;
|
||||
|
||||
if(l->count > 0) {
|
||||
// fetch count, then check remaining length
|
||||
i = l->count;
|
||||
a = nil;
|
||||
b = n->right;
|
||||
while(i > 0) {
|
||||
b = nextarg(b, &a);
|
||||
i--;
|
||||
}
|
||||
if(a == Z) {
|
||||
diag(n, "can't find count arg");
|
||||
return;
|
||||
}
|
||||
if(a->op != OCONST || !typechl[a->type->etype]) {
|
||||
diag(n, "count is invalid constant");
|
||||
return;
|
||||
}
|
||||
j = a->vconst;
|
||||
i = 0;
|
||||
while(b != Z) {
|
||||
b = nextarg(b, &a);
|
||||
i++;
|
||||
}
|
||||
if(i != j)
|
||||
diag(n, "found %d argument%s after count %d", i, i == 1 ? "" : "s", j);
|
||||
}
|
||||
|
||||
if(l->prot != nil) {
|
||||
// check that all arguments after param or count
|
||||
// are listed in type list.
|
||||
i = l->count;
|
||||
if(i == 0)
|
||||
i = l->param;
|
||||
if(i == 0)
|
||||
return;
|
||||
a = nil;
|
||||
b = n->right;
|
||||
while(i > 0) {
|
||||
b = nextarg(b, &a);
|
||||
i--;
|
||||
}
|
||||
if(a == Z) {
|
||||
diag(n, "can't find count/param arg");
|
||||
return;
|
||||
}
|
||||
while(b != Z) {
|
||||
b = nextarg(b, &a);
|
||||
for(tl=l->prot; tl; tl=tl->link)
|
||||
if(sametype(a->type, tl->type))
|
||||
break;
|
||||
if(tl == nil)
|
||||
diag(a, "invalid type %T in call to %s", a->type, s);
|
||||
}
|
||||
}
|
||||
|
||||
if(l->param <= 0)
|
||||
return;
|
||||
i = l->param;
|
||||
a = nil;
|
||||
b = n->right;
|
||||
while(i > 0) {
|
||||
b = nextarg(b, &a);
|
||||
i--;
|
||||
}
|
||||
if(a == Z) {
|
||||
diag(n, "can't find format arg");
|
||||
return;
|
||||
}
|
||||
if(!sametype(indchar, a->type)) {
|
||||
diag(n, "format arg type %T", a->type);
|
||||
return;
|
||||
}
|
||||
if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
|
||||
/* warn(n, "format arg not constant string");*/
|
||||
return;
|
||||
}
|
||||
s = a->left->cstring;
|
||||
checkargs(b, s, l->param);
|
||||
}
|
||||
|
||||
void
|
||||
pragpack(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
packflg = 0;
|
||||
s = getsym();
|
||||
if(s) {
|
||||
packflg = atoi(s->name+1);
|
||||
if(strcmp(s->name, "on") == 0 ||
|
||||
strcmp(s->name, "yes") == 0)
|
||||
packflg = 1;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
if(packflg)
|
||||
print("%4d: pack %d\n", lineno, packflg);
|
||||
else
|
||||
print("%4d: pack off\n", lineno);
|
||||
}
|
||||
|
||||
void
|
||||
pragfpround(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
fproundflg = 0;
|
||||
s = getsym();
|
||||
if(s) {
|
||||
fproundflg = atoi(s->name+1);
|
||||
if(strcmp(s->name, "on") == 0 ||
|
||||
strcmp(s->name, "yes") == 0)
|
||||
fproundflg = 1;
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
if(fproundflg)
|
||||
print("%4d: fproundflg %d\n", lineno, fproundflg);
|
||||
else
|
||||
print("%4d: fproundflg off\n", lineno);
|
||||
}
|
||||
|
||||
void
|
||||
pragtextflag(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
s = getsym();
|
||||
if(s == S) {
|
||||
textflag = getnsn();
|
||||
} else {
|
||||
if(s->macro) {
|
||||
macexpand(s, symb);
|
||||
}
|
||||
if(symb[0] < '0' || symb[0] > '9')
|
||||
yyerror("pragma textflag not an integer");
|
||||
textflag = atoi(symb);
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
print("%4d: textflag %d\n", lineno, textflag);
|
||||
}
|
||||
|
||||
void
|
||||
pragdataflag(void)
|
||||
{
|
||||
Sym *s;
|
||||
|
||||
s = getsym();
|
||||
if(s == S) {
|
||||
dataflag = getnsn();
|
||||
} else {
|
||||
if(s->macro) {
|
||||
macexpand(s, symb);
|
||||
}
|
||||
if(symb[0] < '0' || symb[0] > '9')
|
||||
yyerror("pragma dataflag not an integer");
|
||||
dataflag = atoi(symb);
|
||||
}
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
print("%4d: dataflag %d\n", lineno, dataflag);
|
||||
}
|
||||
|
||||
void
|
||||
pragincomplete(void)
|
||||
{
|
||||
Sym *s;
|
||||
Type *t;
|
||||
int istag, w, et;
|
||||
|
||||
istag = 0;
|
||||
s = getsym();
|
||||
if(s == nil)
|
||||
goto out;
|
||||
et = 0;
|
||||
w = s->lexical;
|
||||
if(w == LSTRUCT)
|
||||
et = TSTRUCT;
|
||||
else if(w == LUNION)
|
||||
et = TUNION;
|
||||
if(et != 0){
|
||||
s = getsym();
|
||||
if(s == nil){
|
||||
yyerror("missing struct/union tag in pragma incomplete");
|
||||
goto out;
|
||||
}
|
||||
if(s->lexical != LNAME && s->lexical != LTYPE){
|
||||
yyerror("invalid struct/union tag: %s", s->name);
|
||||
goto out;
|
||||
}
|
||||
dotag(s, et, 0);
|
||||
istag = 1;
|
||||
}else if(strcmp(s->name, "_off_") == 0){
|
||||
debug['T'] = 0;
|
||||
goto out;
|
||||
}else if(strcmp(s->name, "_on_") == 0){
|
||||
debug['T'] = 1;
|
||||
goto out;
|
||||
}
|
||||
t = s->type;
|
||||
if(istag)
|
||||
t = s->suetag;
|
||||
if(t == T)
|
||||
yyerror("unknown type %s in pragma incomplete", s->name);
|
||||
else if(!typesu[t->etype])
|
||||
yyerror("not struct/union type in pragma incomplete: %s", s->name);
|
||||
else
|
||||
t->garb |= GINCOMPLETE;
|
||||
out:
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
if(debug['f'])
|
||||
print("%s incomplete\n", s->name);
|
||||
}
|
||||
|
||||
Sym*
|
||||
getimpsym(void)
|
||||
{
|
||||
int c;
|
||||
char *cp;
|
||||
|
||||
c = getnsc();
|
||||
if(isspace(c) || c == '"') {
|
||||
unget(c);
|
||||
return S;
|
||||
}
|
||||
for(cp = symb;;) {
|
||||
if(cp <= symb+NSYMB-4)
|
||||
*cp++ = c;
|
||||
c = getc();
|
||||
if(c > 0 && !isspace(c) && c != '"')
|
||||
continue;
|
||||
unget(c);
|
||||
break;
|
||||
}
|
||||
*cp = 0;
|
||||
if(cp > symb+NSYMB-4)
|
||||
yyerror("symbol too large: %s", symb);
|
||||
return lookup();
|
||||
}
|
||||
|
||||
static int
|
||||
more(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
do
|
||||
c = getnsc();
|
||||
while(c == ' ' || c == '\t');
|
||||
unget(c);
|
||||
return c != '\n';
|
||||
}
|
||||
|
||||
void
|
||||
pragcgo(char *verb)
|
||||
{
|
||||
Sym *local, *remote;
|
||||
char *p;
|
||||
|
||||
if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
|
||||
p = getquoted();
|
||||
if(p == nil)
|
||||
goto err1;
|
||||
fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
|
||||
goto out;
|
||||
|
||||
err1:
|
||||
yyerror("usage: #pragma cgo_dynamic_linker \"path\"");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "dynexport") == 0)
|
||||
verb = "cgo_export_dynamic";
|
||||
if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
|
||||
local = getimpsym();
|
||||
if(local == nil)
|
||||
goto err2;
|
||||
if(!more()) {
|
||||
fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
|
||||
goto out;
|
||||
}
|
||||
remote = getimpsym();
|
||||
if(remote == nil)
|
||||
goto err2;
|
||||
fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
|
||||
goto out;
|
||||
|
||||
err2:
|
||||
yyerror("usage: #pragma %s local [remote]", verb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
|
||||
local = getimpsym();
|
||||
if(local == nil)
|
||||
goto err3;
|
||||
if(!more()) {
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local->name);
|
||||
goto out;
|
||||
}
|
||||
remote = getimpsym();
|
||||
if(remote == nil)
|
||||
goto err3;
|
||||
if(!more()) {
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local->name, remote->name);
|
||||
goto out;
|
||||
}
|
||||
p = getquoted();
|
||||
if(p == nil)
|
||||
goto err3;
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local->name, remote->name, p);
|
||||
goto out;
|
||||
|
||||
err3:
|
||||
yyerror("usage: #pragma cgo_import_dynamic local [remote [\"library\"]]");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_import_static") == 0) {
|
||||
local = getimpsym();
|
||||
if(local == nil)
|
||||
goto err4;
|
||||
fmtprint(&pragcgobuf, "cgo_import_static %q\n", local->name);
|
||||
goto out;
|
||||
|
||||
err4:
|
||||
yyerror("usage: #pragma cgo_import_static local [remote]");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_ldflag") == 0) {
|
||||
p = getquoted();
|
||||
if(p == nil)
|
||||
goto err5;
|
||||
fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
|
||||
goto out;
|
||||
|
||||
err5:
|
||||
yyerror("usage: #pragma cgo_ldflag \"arg\"");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
while(getnsc() != '\n')
|
||||
;
|
||||
}
|
@ -1,431 +0,0 @@
|
||||
// Inferno utils/cc/funct.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/funct.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 "cc.h"
|
||||
|
||||
typedef struct Ftab Ftab;
|
||||
struct Ftab
|
||||
{
|
||||
char op;
|
||||
char* name;
|
||||
char typ;
|
||||
};
|
||||
typedef struct Gtab Gtab;
|
||||
struct Gtab
|
||||
{
|
||||
char etype;
|
||||
char* name;
|
||||
};
|
||||
|
||||
Ftab ftabinit[OEND];
|
||||
Gtab gtabinit[NALLTYPES];
|
||||
|
||||
int
|
||||
isfunct(Node *n)
|
||||
{
|
||||
Type *t, *t1;
|
||||
Funct *f;
|
||||
Node *l;
|
||||
Sym *s;
|
||||
int o;
|
||||
|
||||
o = n->op;
|
||||
if(n->left == Z)
|
||||
goto no;
|
||||
t = n->left->type;
|
||||
if(t == T)
|
||||
goto no;
|
||||
f = t->funct;
|
||||
|
||||
switch(o) {
|
||||
case OAS: // put cast on rhs
|
||||
case OASI:
|
||||
case OASADD:
|
||||
case OASAND:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASLMUL:
|
||||
case OASLSHR:
|
||||
case OASMOD:
|
||||
case OASMUL:
|
||||
case OASOR:
|
||||
case OASSUB:
|
||||
case OASXOR:
|
||||
if(n->right == Z)
|
||||
goto no;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto no;
|
||||
if(t1->funct == f)
|
||||
break;
|
||||
|
||||
l = new(OXXX, Z, Z);
|
||||
*l = *n->right;
|
||||
|
||||
n->right->left = l;
|
||||
n->right->right = Z;
|
||||
n->right->type = t;
|
||||
n->right->op = OCAST;
|
||||
|
||||
if(!isfunct(n->right))
|
||||
prtree(n, "isfunc !");
|
||||
break;
|
||||
|
||||
case OCAST: // t f(T) or T f(t)
|
||||
t1 = n->type;
|
||||
if(t1 == T)
|
||||
goto no;
|
||||
if(f != nil) {
|
||||
s = f->castfr[t1->etype];
|
||||
if(s == S)
|
||||
goto no;
|
||||
n->right = n->left;
|
||||
goto build;
|
||||
}
|
||||
f = t1->funct;
|
||||
if(f != nil) {
|
||||
s = f->castto[t->etype];
|
||||
if(s == S)
|
||||
goto no;
|
||||
n->right = n->left;
|
||||
goto build;
|
||||
}
|
||||
goto no;
|
||||
}
|
||||
|
||||
if(f == nil)
|
||||
goto no;
|
||||
s = f->sym[o];
|
||||
if(s == S)
|
||||
goto no;
|
||||
|
||||
/*
|
||||
* the answer is yes,
|
||||
* now we rewrite the node
|
||||
* and give diagnostics
|
||||
*/
|
||||
switch(o) {
|
||||
default:
|
||||
diag(n, "isfunct op missing %O\n", o);
|
||||
goto bad;
|
||||
|
||||
case OADD: // T f(T, T)
|
||||
case OAND:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case ODIV:
|
||||
case OLDIV:
|
||||
case OLMOD:
|
||||
case OLMUL:
|
||||
case OLSHR:
|
||||
case OMOD:
|
||||
case OMUL:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
|
||||
case OEQ: // int f(T, T)
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLE:
|
||||
case OLO:
|
||||
case OLS:
|
||||
case OLT:
|
||||
case ONE:
|
||||
if(n->right == Z)
|
||||
goto bad;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto bad;
|
||||
if(t1->funct != f)
|
||||
goto bad;
|
||||
n->right = new(OLIST, n->left, n->right);
|
||||
break;
|
||||
|
||||
case OAS: // structure copies done by the compiler
|
||||
case OASI:
|
||||
goto no;
|
||||
|
||||
case OASADD: // T f(T*, T)
|
||||
case OASAND:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASDIV:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASLMUL:
|
||||
case OASLSHR:
|
||||
case OASMOD:
|
||||
case OASMUL:
|
||||
case OASOR:
|
||||
case OASSUB:
|
||||
case OASXOR:
|
||||
if(n->right == Z)
|
||||
goto bad;
|
||||
t1 = n->right->type;
|
||||
if(t1 == T)
|
||||
goto bad;
|
||||
if(t1->funct != f)
|
||||
goto bad;
|
||||
n->right = new(OLIST, new(OADDR, n->left, Z), n->right);
|
||||
break;
|
||||
|
||||
case OPOS: // T f(T)
|
||||
case ONEG:
|
||||
case ONOT:
|
||||
case OCOM:
|
||||
n->right = n->left;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
build:
|
||||
l = new(ONAME, Z, Z);
|
||||
l->sym = s;
|
||||
l->type = s->type;
|
||||
l->etype = s->type->etype;
|
||||
l->xoffset = s->offset;
|
||||
l->class = s->class;
|
||||
tcomo(l, 0);
|
||||
|
||||
n->op = OFUNC;
|
||||
n->left = l;
|
||||
n->type = l->type->link;
|
||||
if(tcompat(n, T, l->type, tfunct))
|
||||
goto bad;
|
||||
if(tcoma(n->left, n->right, l->type->down, 1))
|
||||
goto bad;
|
||||
return 1;
|
||||
|
||||
no:
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
diag(n, "can't rewrite typestr for op %O\n", o);
|
||||
prtree(n, "isfunct");
|
||||
n->type = T;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dclfunct(Type *t, Sym *s)
|
||||
{
|
||||
Funct *f;
|
||||
Node *n;
|
||||
Type *f1, *f2, *f3, *f4;
|
||||
int o, i, c;
|
||||
char str[100];
|
||||
|
||||
if(t->funct)
|
||||
return;
|
||||
|
||||
// recognize generated tag of dorm _%d_
|
||||
if(t->tag == S)
|
||||
goto bad;
|
||||
for(i=0; c = t->tag->name[i]; i++) {
|
||||
if(c == '_') {
|
||||
if(i == 0 || t->tag->name[i+1] == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(c < '0' || c > '9')
|
||||
break;
|
||||
}
|
||||
if(c == 0)
|
||||
goto bad;
|
||||
|
||||
f = alloc(sizeof(*f));
|
||||
for(o=0; o<nelem(f->sym); o++)
|
||||
f->sym[o] = S;
|
||||
|
||||
t->funct = f;
|
||||
|
||||
f1 = typ(TFUNC, t);
|
||||
f1->down = copytyp(t);
|
||||
f1->down->down = t;
|
||||
|
||||
f2 = typ(TFUNC, types[TINT]);
|
||||
f2->down = copytyp(t);
|
||||
f2->down->down = t;
|
||||
|
||||
f3 = typ(TFUNC, t);
|
||||
f3->down = typ(TIND, t);
|
||||
f3->down->down = t;
|
||||
|
||||
f4 = typ(TFUNC, t);
|
||||
f4->down = t;
|
||||
|
||||
for(i=0;; i++) {
|
||||
o = ftabinit[i].op;
|
||||
if(o == OXXX)
|
||||
break;
|
||||
sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->sym[o] = n->sym;
|
||||
switch(ftabinit[i].typ) {
|
||||
default:
|
||||
diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ);
|
||||
break;
|
||||
|
||||
case 1: // T f(T,T) +
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
break;
|
||||
|
||||
case 2: // int f(T,T) ==
|
||||
dodecl(xdecl, CEXTERN, f2, n);
|
||||
break;
|
||||
|
||||
case 3: // void f(T*,T) +=
|
||||
dodecl(xdecl, CEXTERN, f3, n);
|
||||
break;
|
||||
|
||||
case 4: // T f(T) ~
|
||||
dodecl(xdecl, CEXTERN, f4, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i=0;; i++) {
|
||||
o = gtabinit[i].etype;
|
||||
if(o == TXXX)
|
||||
break;
|
||||
|
||||
/*
|
||||
* OCAST types T1 _T2_T1_(T2)
|
||||
*/
|
||||
sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->castto[o] = n->sym;
|
||||
|
||||
f1 = typ(TFUNC, t);
|
||||
f1->down = types[o];
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
|
||||
sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name);
|
||||
n = new(ONAME, Z, Z);
|
||||
n->sym = slookup(str);
|
||||
f->castfr[o] = n->sym;
|
||||
|
||||
f1 = typ(TFUNC, types[o]);
|
||||
f1->down = t;
|
||||
dodecl(xdecl, CEXTERN, f1, n);
|
||||
}
|
||||
return;
|
||||
bad:
|
||||
diag(Z, "dclfunct bad %T %s\n", t, s->name);
|
||||
}
|
||||
|
||||
Gtab gtabinit[NALLTYPES] =
|
||||
{
|
||||
TCHAR, "c",
|
||||
TUCHAR, "uc",
|
||||
TSHORT, "h",
|
||||
TUSHORT, "uh",
|
||||
TINT, "i",
|
||||
TUINT, "ui",
|
||||
TLONG, "l",
|
||||
TULONG, "ul",
|
||||
TVLONG, "v",
|
||||
TUVLONG, "uv",
|
||||
TFLOAT, "f",
|
||||
TDOUBLE, "d",
|
||||
TXXX
|
||||
};
|
||||
|
||||
Ftab ftabinit[OEND] =
|
||||
{
|
||||
OADD, "add", 1,
|
||||
OAND, "and", 1,
|
||||
OASHL, "ashl", 1,
|
||||
OASHR, "ashr", 1,
|
||||
ODIV, "div", 1,
|
||||
OLDIV, "ldiv", 1,
|
||||
OLMOD, "lmod", 1,
|
||||
OLMUL, "lmul", 1,
|
||||
OLSHR, "lshr", 1,
|
||||
OMOD, "mod", 1,
|
||||
OMUL, "mul", 1,
|
||||
OOR, "or", 1,
|
||||
OSUB, "sub", 1,
|
||||
OXOR, "xor", 1,
|
||||
|
||||
OEQ, "eq", 2,
|
||||
OGE, "ge", 2,
|
||||
OGT, "gt", 2,
|
||||
OHI, "hi", 2,
|
||||
OHS, "hs", 2,
|
||||
OLE, "le", 2,
|
||||
OLO, "lo", 2,
|
||||
OLS, "ls", 2,
|
||||
OLT, "lt", 2,
|
||||
ONE, "ne", 2,
|
||||
|
||||
OASADD, "asadd", 3,
|
||||
OASAND, "asand", 3,
|
||||
OASASHL, "asashl", 3,
|
||||
OASASHR, "asashr", 3,
|
||||
OASDIV, "asdiv", 3,
|
||||
OASLDIV, "asldiv", 3,
|
||||
OASLMOD, "aslmod", 3,
|
||||
OASLMUL, "aslmul", 3,
|
||||
OASLSHR, "aslshr", 3,
|
||||
OASMOD, "asmod", 3,
|
||||
OASMUL, "asmul", 3,
|
||||
OASOR, "asor", 3,
|
||||
OASSUB, "assub", 3,
|
||||
OASXOR, "asxor", 3,
|
||||
|
||||
OPOS, "pos", 4,
|
||||
ONEG, "neg", 4,
|
||||
OCOM, "com", 4,
|
||||
ONOT, "not", 4,
|
||||
|
||||
// OPOSTDEC,
|
||||
// OPOSTINC,
|
||||
// OPREDEC,
|
||||
// OPREINC,
|
||||
|
||||
OXXX,
|
||||
};
|
||||
|
||||
// Node* nodtestv;
|
||||
|
||||
// Node* nodvpp;
|
||||
// Node* nodppv;
|
||||
// Node* nodvmm;
|
||||
// Node* nodmmv;
|
@ -1,367 +0,0 @@
|
||||
// cmd/cc/godefs.cc
|
||||
//
|
||||
// derived from pickle.cc which itself was derived from acid.cc.
|
||||
//
|
||||
// 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-2011 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 "cc.h"
|
||||
|
||||
static int upper;
|
||||
|
||||
static char *kwd[] =
|
||||
{
|
||||
"_bool",
|
||||
"_break",
|
||||
"_byte",
|
||||
"_case",
|
||||
"_chan",
|
||||
"_complex128",
|
||||
"_complex64",
|
||||
"_const",
|
||||
"_continue",
|
||||
"_default",
|
||||
"_defer",
|
||||
"_else",
|
||||
"_fallthrough",
|
||||
"_false",
|
||||
"_float32",
|
||||
"_float64",
|
||||
"_for",
|
||||
"_func",
|
||||
"_go",
|
||||
"_goto",
|
||||
"_if",
|
||||
"_import",
|
||||
"_int",
|
||||
"_int16",
|
||||
"_int32",
|
||||
"_int64",
|
||||
"_int8",
|
||||
"_interface",
|
||||
"_intptr",
|
||||
"_map",
|
||||
"_package",
|
||||
"_panic",
|
||||
"_range",
|
||||
"_return",
|
||||
"_select",
|
||||
"_string",
|
||||
"_struct",
|
||||
"_switch",
|
||||
"_true",
|
||||
"_type",
|
||||
"_uint",
|
||||
"_uint16",
|
||||
"_uint32",
|
||||
"_uint64",
|
||||
"_uint8",
|
||||
"_uintptr",
|
||||
"_var",
|
||||
};
|
||||
|
||||
static char*
|
||||
pmap(char *s)
|
||||
{
|
||||
int i, bot, top, mid;
|
||||
|
||||
bot = -1;
|
||||
top = nelem(kwd);
|
||||
while(top - bot > 1){
|
||||
mid = (bot + top) / 2;
|
||||
i = strcmp(kwd[mid]+1, s);
|
||||
if(i == 0)
|
||||
return kwd[mid];
|
||||
if(i < 0)
|
||||
bot = mid;
|
||||
else
|
||||
top = mid;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Uconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ+1];
|
||||
char *s, *n;
|
||||
int i;
|
||||
|
||||
str[0] = 0;
|
||||
s = va_arg(fp->args, char*);
|
||||
|
||||
// strip package name
|
||||
n = strrchr(s, '.');
|
||||
if(n != nil)
|
||||
s = n + 1;
|
||||
|
||||
if(s && *s) {
|
||||
if(upper)
|
||||
str[0] = toupper((uchar)*s);
|
||||
else
|
||||
str[0] = tolower((uchar)*s);
|
||||
for(i = 1; i < STRINGSZ && s[i] != 0; i++)
|
||||
str[i] = tolower((uchar)s[i]);
|
||||
str[i] = 0;
|
||||
}
|
||||
|
||||
return fmtstrcpy(fp, pmap(str));
|
||||
}
|
||||
|
||||
|
||||
static Sym*
|
||||
findsue(Type *t)
|
||||
{
|
||||
int h;
|
||||
Sym *s;
|
||||
|
||||
if(t != T)
|
||||
for(h=0; h<nelem(hash); h++)
|
||||
for(s = hash[h]; s != S; s = s->link)
|
||||
if(s->suetag && s->suetag->link == t)
|
||||
return s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
printtypename(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
int w;
|
||||
char *n;
|
||||
|
||||
for( ; t != nil; t = t->link) {
|
||||
switch(t->etype) {
|
||||
case TIND:
|
||||
// Special handling of *void.
|
||||
if(t->link != nil && t->link->etype==TVOID) {
|
||||
Bprint(&outbuf, "unsafe.Pointer");
|
||||
return;
|
||||
}
|
||||
// *func == func
|
||||
if(t->link != nil && t->link->etype==TFUNC)
|
||||
continue;
|
||||
Bprint(&outbuf, "*");
|
||||
continue;
|
||||
case TARRAY:
|
||||
w = t->width;
|
||||
if(t->link && t->link->width)
|
||||
w /= t->link->width;
|
||||
Bprint(&outbuf, "[%d]", w);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(t == nil) {
|
||||
Bprint(&outbuf, "bad // should not happen");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(t->etype) {
|
||||
case TINT:
|
||||
case TUINT:
|
||||
case TCHAR:
|
||||
case TUCHAR:
|
||||
case TSHORT:
|
||||
case TUSHORT:
|
||||
case TLONG:
|
||||
case TULONG:
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
// All names used in the runtime code should be typedefs.
|
||||
if(t->tag != nil) {
|
||||
if(strcmp(t->tag->name, "intgo") == 0)
|
||||
Bprint(&outbuf, "int");
|
||||
else if(strcmp(t->tag->name, "uintgo") == 0)
|
||||
Bprint(&outbuf, "uint");
|
||||
else
|
||||
Bprint(&outbuf, "%s", t->tag->name);
|
||||
} else
|
||||
Bprint(&outbuf, "C.%T", t);
|
||||
break;
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
s = findsue(t->link);
|
||||
n = "bad";
|
||||
if(s != S)
|
||||
n = s->name;
|
||||
else if(t->tag)
|
||||
n = t->tag->name;
|
||||
if(strcmp(n, "String") == 0)
|
||||
Bprint(&outbuf, "string");
|
||||
else if(strcmp(n, "Slice") == 0)
|
||||
Bprint(&outbuf, "[]byte");
|
||||
else if(strcmp(n, "Eface") == 0)
|
||||
Bprint(&outbuf, "interface{}");
|
||||
else
|
||||
Bprint(&outbuf, "%U", n);
|
||||
break;
|
||||
case TFUNC:
|
||||
// There's no equivalent to a C function in the Go world.
|
||||
Bprint(&outbuf, "unsafe.Pointer");
|
||||
break;
|
||||
case TDOT:
|
||||
Bprint(&outbuf, "...interface{}");
|
||||
break;
|
||||
default:
|
||||
Bprint(&outbuf, " weird<%T>", t);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dontrun(void)
|
||||
{
|
||||
Io *i;
|
||||
int n;
|
||||
|
||||
if(!debug['q'] && !debug['Q'])
|
||||
return 1;
|
||||
if(debug['q'] + debug['Q'] > 1) {
|
||||
n = 0;
|
||||
for(i=iostack; i; i=i->link)
|
||||
n++;
|
||||
if(n > 1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
upper = debug['Q'];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
godeftype(Type *t)
|
||||
{
|
||||
Sym *s;
|
||||
Type *l;
|
||||
int gotone;
|
||||
|
||||
if(dontrun())
|
||||
return;
|
||||
|
||||
switch(t->etype) {
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
s = findsue(t->link);
|
||||
if(s == S) {
|
||||
Bprint(&outbuf, "/* can't find %T */\n\n", t);
|
||||
return;
|
||||
}
|
||||
|
||||
gotone = 0; // for unions, take first member of size equal to union
|
||||
Bprint(&outbuf, "type %U struct {\n", s->name);
|
||||
for(l = t->link; l != T; l = l->down) {
|
||||
Bprint(&outbuf, "\t");
|
||||
if(t->etype == TUNION) {
|
||||
if(!gotone && l->width == t->width)
|
||||
gotone = 1;
|
||||
else
|
||||
Bprint(&outbuf, "// (union)\t");
|
||||
}
|
||||
if(l->sym != nil) // not anonymous field
|
||||
Bprint(&outbuf, "%U\t", l->sym->name);
|
||||
printtypename(l);
|
||||
Bprint(&outbuf, "\n");
|
||||
}
|
||||
Bprint(&outbuf, "}\n\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
Bprint(&outbuf, "/* %T */\n\n", t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
godefvar(Sym *s)
|
||||
{
|
||||
Type *t, *t1;
|
||||
char n;
|
||||
|
||||
if(dontrun())
|
||||
return;
|
||||
|
||||
t = s->type;
|
||||
if(t == nil)
|
||||
return;
|
||||
|
||||
switch(t->etype) {
|
||||
case TENUM:
|
||||
if(!typefd[t->etype])
|
||||
Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst);
|
||||
else
|
||||
Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst);
|
||||
break;
|
||||
|
||||
case TFUNC:
|
||||
Bprint(&outbuf, "func %U(", s->name);
|
||||
n = 'a';
|
||||
for(t1 = t->down; t1 != T; t1 = t1->down) {
|
||||
if(t1->etype == TVOID)
|
||||
break;
|
||||
if(t1 != t->down)
|
||||
Bprint(&outbuf, ", ");
|
||||
Bprint(&outbuf, "%c ", n++);
|
||||
printtypename(t1);
|
||||
}
|
||||
Bprint(&outbuf, ")");
|
||||
if(t->link && t->link->etype != TVOID) {
|
||||
Bprint(&outbuf, " ");
|
||||
printtypename(t->link);
|
||||
}
|
||||
Bprint(&outbuf, "\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
switch(s->class) {
|
||||
case CTYPEDEF:
|
||||
if(!typesu[t->etype]) {
|
||||
Bprint(&outbuf, "// type %U\t", s->name);
|
||||
printtypename(t);
|
||||
Bprint(&outbuf, "\n");
|
||||
}
|
||||
break;
|
||||
case CSTATIC:
|
||||
case CEXTERN:
|
||||
case CGLOBL:
|
||||
if(strchr(s->name, '$') != nil)
|
||||
break;
|
||||
if(strncmp(s->name, "go.weak.", 8) == 0)
|
||||
break;
|
||||
Bprint(&outbuf, "var %U\t", s->name);
|
||||
printtypename(t);
|
||||
Bprint(&outbuf, "\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
1593
src/cmd/cc/lex.c
1593
src/cmd/cc/lex.c
File diff suppressed because it is too large
Load Diff
@ -1,34 +0,0 @@
|
||||
// Inferno utils/cc/mac.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/mac.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 "cc.h"
|
||||
|
||||
#include "macbody"
|
@ -1,40 +0,0 @@
|
||||
// Inferno utils/cc/machcap.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/machcap.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 "cc.h"
|
||||
|
||||
/* default, like old cc */
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
USED(n);
|
||||
return 0;
|
||||
}
|
@ -1,622 +0,0 @@
|
||||
// Inferno utils/6c/sgen.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.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 "gc.h"
|
||||
#include "../../runtime/funcdata.h"
|
||||
|
||||
int
|
||||
hasdotdotdot(Type *t)
|
||||
{
|
||||
for(t=t->down; t!=T; t=t->down)
|
||||
if(t->etype == TDOT)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vlong
|
||||
argsize(int doret)
|
||||
{
|
||||
Type *t;
|
||||
int32 s;
|
||||
|
||||
//print("t=%T\n", thisfn);
|
||||
s = 0;
|
||||
if(hasdotdotdot(thisfn))
|
||||
s = align(s, thisfn->link, Aarg0, nil);
|
||||
for(t=thisfn->down; t!=T; t=t->down) {
|
||||
switch(t->etype) {
|
||||
case TVOID:
|
||||
break;
|
||||
case TDOT:
|
||||
if((textflag & NOSPLIT) == 0)
|
||||
yyerror("function takes ... without textflag NOSPLIT");
|
||||
return ArgsSizeUnknown;
|
||||
default:
|
||||
s = align(s, t, Aarg1, nil);
|
||||
s = align(s, t, Aarg2, nil);
|
||||
break;
|
||||
}
|
||||
//print(" %d %T\n", s, t);
|
||||
}
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = (s+7) & ~7;
|
||||
else
|
||||
s = (s+3) & ~3;
|
||||
if(doret && thisfn->link->etype != TVOID) {
|
||||
s = align(s, thisfn->link, Aarg1, nil);
|
||||
s = align(s, thisfn->link, Aarg2, nil);
|
||||
if(thechar == '6' || thechar == '9')
|
||||
s = (s+7) & ~7;
|
||||
else
|
||||
s = (s+3) & ~3;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
codgen(Node *n, Node *nn)
|
||||
{
|
||||
Prog *sp;
|
||||
Node *n1, nod, nod1;
|
||||
|
||||
cursafe = 0;
|
||||
curarg = 0;
|
||||
maxargsafe = 0;
|
||||
|
||||
/*
|
||||
* isolate name
|
||||
*/
|
||||
for(n1 = nn;; n1 = n1->left) {
|
||||
if(n1 == Z) {
|
||||
diag(nn, "can't find function name");
|
||||
return;
|
||||
}
|
||||
if(n1->op == ONAME)
|
||||
break;
|
||||
}
|
||||
nearln = nn->lineno;
|
||||
|
||||
p = gtext(n1->sym, stkoff);
|
||||
p->from.sym->cfunc = 1;
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* isolate first argument
|
||||
*/
|
||||
if(REGARG >= 0) {
|
||||
if(typesuv[thisfn->link->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
} else
|
||||
if(firstarg && typechlp[firstargtype->etype]) {
|
||||
nod1 = *nodret->left;
|
||||
nod1.sym = firstarg;
|
||||
nod1.type = firstargtype;
|
||||
nod1.xoffset = align(0, firstargtype, Aarg1, nil);
|
||||
nod1.etype = firstargtype->etype;
|
||||
nodreg(&nod, &nod1, REGARG);
|
||||
gmove(&nod, &nod1);
|
||||
}
|
||||
}
|
||||
|
||||
canreach = 1;
|
||||
warnreach = 1;
|
||||
gen(n);
|
||||
if(canreach && thisfn->link->etype != TVOID)
|
||||
diag(Z, "no return at end of function: %s", n1->sym->name);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
|
||||
if(!debug['N'] || debug['R'] || debug['P'])
|
||||
regopt(sp);
|
||||
|
||||
if(thechar=='6' || thechar=='7') /* [sic] */
|
||||
maxargsafe = xround(maxargsafe, 8);
|
||||
sp->to.offset += maxargsafe;
|
||||
}
|
||||
|
||||
void
|
||||
supgen(Node *n)
|
||||
{
|
||||
int owarn;
|
||||
long spc;
|
||||
Prog *sp;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
suppress++;
|
||||
owarn = warnreach;
|
||||
warnreach = 0;
|
||||
spc = pc;
|
||||
sp = lastp;
|
||||
gen(n);
|
||||
lastp = sp;
|
||||
pc = spc;
|
||||
sp->link = nil;
|
||||
suppress--;
|
||||
warnreach = owarn;
|
||||
}
|
||||
|
||||
void
|
||||
gen(Node *n)
|
||||
{
|
||||
Node *l, nod, nod1;
|
||||
Prog *sp, *spc, *spb;
|
||||
Case *cn;
|
||||
long sbc, scc;
|
||||
int snbreak, sncontin;
|
||||
int f, o, oldreach;
|
||||
|
||||
loop:
|
||||
if(n == Z)
|
||||
return;
|
||||
nearln = n->lineno;
|
||||
o = n->op;
|
||||
if(debug['G'])
|
||||
if(o != OLIST)
|
||||
print("%L %O\n", nearln, o);
|
||||
|
||||
if(!canreach) {
|
||||
switch(o) {
|
||||
case OLABEL:
|
||||
case OCASE:
|
||||
case OLIST:
|
||||
case OBREAK:
|
||||
case OFOR:
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
/* all handled specially - see switch body below */
|
||||
break;
|
||||
default:
|
||||
if(warnreach) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(o) {
|
||||
|
||||
default:
|
||||
complex(n);
|
||||
cgen(n, Z);
|
||||
break;
|
||||
|
||||
case OLIST:
|
||||
gen(n->left);
|
||||
|
||||
rloop:
|
||||
n = n->right;
|
||||
goto loop;
|
||||
|
||||
case ORETURN:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
complex(n);
|
||||
if(n->type == T)
|
||||
break;
|
||||
l = n->left;
|
||||
if(l == Z) {
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
|
||||
regret(&nod, n, thisfn, 2);
|
||||
sugen(l, &nod, n->type->width);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
if(typecmplx[n->type->etype]) {
|
||||
sugen(l, nodret, n->type->width);
|
||||
noretval(3);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
}
|
||||
regret(&nod1, n, thisfn, 2);
|
||||
nod = nod1;
|
||||
if(nod.op != OREGISTER)
|
||||
regalloc(&nod, n, Z);
|
||||
cgen(l, &nod);
|
||||
if(nod1.op != OREGISTER)
|
||||
gmove(&nod, &nod1);
|
||||
regfree(&nod);
|
||||
if(typefd[n->type->etype])
|
||||
noretval(1);
|
||||
else
|
||||
noretval(2);
|
||||
gbranch(ORETURN);
|
||||
break;
|
||||
|
||||
case OLABEL:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(l) {
|
||||
l->pc = pc;
|
||||
if(l->label)
|
||||
patch(l->label, pc);
|
||||
}
|
||||
gbranch(OGOTO); /* prevent self reference in reg */
|
||||
patch(p, pc);
|
||||
goto rloop;
|
||||
|
||||
case OGOTO:
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
n = n->left;
|
||||
if(n == Z)
|
||||
return;
|
||||
if(n->complex == 0) {
|
||||
diag(Z, "label undefined: %s", n->sym->name);
|
||||
return;
|
||||
}
|
||||
if(suppress)
|
||||
return;
|
||||
gbranch(OGOTO);
|
||||
if(n->pc) {
|
||||
patch(p, n->pc);
|
||||
return;
|
||||
}
|
||||
if(n->label)
|
||||
patch(n->label, pc-1);
|
||||
n->label = p;
|
||||
return;
|
||||
|
||||
case OCASE:
|
||||
canreach = 1;
|
||||
l = n->left;
|
||||
if(cases == C)
|
||||
diag(n, "case/default outside a switch");
|
||||
if(l == Z) {
|
||||
newcase();
|
||||
cases->val = 0;
|
||||
cases->def = 1;
|
||||
cases->label = pc;
|
||||
cases->isv = 0;
|
||||
goto rloop;
|
||||
}
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
goto rloop;
|
||||
if(l->op == OCONST)
|
||||
if(typeword[l->type->etype] && l->type->etype != TIND) {
|
||||
newcase();
|
||||
cases->val = l->vconst;
|
||||
cases->def = 0;
|
||||
cases->label = pc;
|
||||
cases->isv = typev[l->type->etype];
|
||||
goto rloop;
|
||||
}
|
||||
diag(n, "case expression must be integer constant");
|
||||
goto rloop;
|
||||
|
||||
case OSWITCH:
|
||||
l = n->left;
|
||||
complex(l);
|
||||
if(l->type == T)
|
||||
break;
|
||||
if(!typechlvp[l->type->etype] || l->type->etype == TIND) {
|
||||
diag(n, "switch expression must be integer");
|
||||
break;
|
||||
}
|
||||
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
cn = cases;
|
||||
cases = C;
|
||||
newcase();
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
}
|
||||
|
||||
patch(sp, pc);
|
||||
doswit(l);
|
||||
patch(spb, pc);
|
||||
|
||||
cases = cn;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OWHILE:
|
||||
case ODWHILE:
|
||||
l = n->left;
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
if(n->op == OWHILE)
|
||||
patch(sp, pc);
|
||||
bcomplex(l, Z); /* test */
|
||||
patch(p, breakpc);
|
||||
if(l->op != OCONST || vconst(l) == 0)
|
||||
nbreak++;
|
||||
|
||||
if(n->op == ODWHILE)
|
||||
patch(sp, pc);
|
||||
gen(n->right); /* body */
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
break;
|
||||
|
||||
case OFOR:
|
||||
l = n->left;
|
||||
if(!canreach && l->right->left && warnreach) {
|
||||
warn(n, "unreachable code FOR");
|
||||
warnreach = 0;
|
||||
}
|
||||
gen(l->right->left); /* init */
|
||||
gbranch(OGOTO); /* entry */
|
||||
sp = p;
|
||||
|
||||
/*
|
||||
* if there are no incoming labels in the
|
||||
* body and the top's not reachable, warn
|
||||
*/
|
||||
if(!canreach && warnreach && deadheads(n)) {
|
||||
warn(n, "unreachable code %O", o);
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
scc = continpc;
|
||||
continpc = pc;
|
||||
gbranch(OGOTO);
|
||||
spc = p;
|
||||
|
||||
sbc = breakpc;
|
||||
breakpc = pc;
|
||||
snbreak = nbreak;
|
||||
nbreak = 0;
|
||||
sncontin = ncontin;
|
||||
ncontin = 0;
|
||||
gbranch(OGOTO);
|
||||
spb = p;
|
||||
|
||||
patch(spc, pc);
|
||||
gen(l->right->right); /* inc */
|
||||
patch(sp, pc);
|
||||
if(l->left != Z) { /* test */
|
||||
bcomplex(l->left, Z);
|
||||
patch(p, breakpc);
|
||||
if(l->left->op != OCONST || vconst(l->left) == 0)
|
||||
nbreak++;
|
||||
}
|
||||
canreach = 1;
|
||||
gen(n->right); /* body */
|
||||
if(canreach){
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
}
|
||||
if(!ncontin && l->right->right && warnreach) {
|
||||
warn(l->right->right, "unreachable FOR inc");
|
||||
warnreach = 0;
|
||||
}
|
||||
|
||||
patch(spb, pc);
|
||||
continpc = scc;
|
||||
breakpc = sbc;
|
||||
canreach = nbreak!=0;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
nbreak = snbreak;
|
||||
ncontin = sncontin;
|
||||
break;
|
||||
|
||||
case OCONTINUE:
|
||||
if(continpc < 0) {
|
||||
diag(n, "continue not in a loop");
|
||||
break;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, continpc);
|
||||
ncontin++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OBREAK:
|
||||
if(breakpc < 0) {
|
||||
diag(n, "break not in a loop");
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Don't complain about unreachable break statements.
|
||||
* There are breaks hidden in yacc's output and some people
|
||||
* write return; break; in their switch statements out of habit.
|
||||
* However, don't confuse the analysis by inserting an
|
||||
* unreachable reference to breakpc either.
|
||||
*/
|
||||
if(!canreach)
|
||||
break;
|
||||
gbranch(OGOTO);
|
||||
patch(p, breakpc);
|
||||
nbreak++;
|
||||
canreach = 0;
|
||||
warnreach = !suppress;
|
||||
break;
|
||||
|
||||
case OIF:
|
||||
l = n->left;
|
||||
if(bcomplex(l, n->right)) {
|
||||
if(typefd[l->type->etype])
|
||||
f = !l->fconst;
|
||||
else
|
||||
f = !l->vconst;
|
||||
if(debug['c'])
|
||||
print("%L const if %s\n", nearln, f ? "false" : "true");
|
||||
if(f) {
|
||||
canreach = 1;
|
||||
supgen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
gen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!canreach && oldreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
}
|
||||
else {
|
||||
canreach = 1;
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
supgen(n->right->right);
|
||||
/*
|
||||
* treat constant ifs as regular ifs for
|
||||
* reachability warnings.
|
||||
*/
|
||||
if(!oldreach && canreach && debug['w'] < 2)
|
||||
warnreach = 0;
|
||||
canreach = oldreach;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sp = p;
|
||||
canreach = 1;
|
||||
if(n->right->left != Z)
|
||||
gen(n->right->left);
|
||||
oldreach = canreach;
|
||||
canreach = 1;
|
||||
if(n->right->right != Z) {
|
||||
gbranch(OGOTO);
|
||||
patch(sp, pc);
|
||||
sp = p;
|
||||
gen(n->right->right);
|
||||
}
|
||||
patch(sp, pc);
|
||||
canreach = canreach || oldreach;
|
||||
if(canreach == 0)
|
||||
warnreach = !suppress;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSET:
|
||||
case OUSED:
|
||||
case OPREFETCH:
|
||||
usedset(n->left, o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usedset(Node *n, int o)
|
||||
{
|
||||
if(n->op == OLIST) {
|
||||
usedset(n->left, o);
|
||||
usedset(n->right, o);
|
||||
return;
|
||||
}
|
||||
complex(n);
|
||||
if(o == OPREFETCH) {
|
||||
gprefetch(n);
|
||||
return;
|
||||
}
|
||||
switch(n->op) {
|
||||
case OADDR: /* volatile */
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
case ONAME:
|
||||
if(o == OSET)
|
||||
gins(ANOP, Z, n);
|
||||
else
|
||||
gins(ANOP, n, Z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bcomplex(Node *n, Node *c)
|
||||
{
|
||||
Node *b, nod;
|
||||
|
||||
complex(n);
|
||||
if(n->type != T)
|
||||
if(tcompat(n, T, n->type, tnot))
|
||||
n->type = T;
|
||||
if(n->type == T) {
|
||||
gbranch(OGOTO);
|
||||
return 0;
|
||||
}
|
||||
if(c != Z && n->op == OCONST && deadheads(c))
|
||||
return 1;
|
||||
if(typev[n->type->etype] && machcap(Z)) {
|
||||
b = &nod;
|
||||
b->op = ONE;
|
||||
b->left = n;
|
||||
b->right = new(0, Z, Z);
|
||||
*b->right = *nodconst(0);
|
||||
b->right->type = n->type;
|
||||
b->type = types[TLONG];
|
||||
n = b;
|
||||
}
|
||||
bool64(n);
|
||||
boolgen(n, 1, Z);
|
||||
return 0;
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
// 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 "gc.h"
|
||||
|
||||
int
|
||||
swcmp(const void *a1, const void *a2)
|
||||
{
|
||||
C1 *p1, *p2;
|
||||
|
||||
p1 = (C1*)a1;
|
||||
p2 = (C1*)a2;
|
||||
if(p1->val < p2->val)
|
||||
return -1;
|
||||
return p1->val > p2->val;
|
||||
}
|
||||
|
||||
void
|
||||
doswit(Node *n)
|
||||
{
|
||||
Case *c;
|
||||
C1 *q, *iq;
|
||||
int32 def, nc, i, isv;
|
||||
|
||||
def = 0;
|
||||
nc = 0;
|
||||
isv = 0;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def) {
|
||||
if(def)
|
||||
diag(n, "more than one default in switch");
|
||||
def = c->label;
|
||||
continue;
|
||||
}
|
||||
isv |= c->isv;
|
||||
nc++;
|
||||
}
|
||||
if(isv && !typev[n->type->etype])
|
||||
warn(n, "32-bit switch expression with 64-bit case constant");
|
||||
|
||||
iq = alloc(nc*sizeof(C1));
|
||||
q = iq;
|
||||
for(c = cases; c->link != C; c = c->link) {
|
||||
if(c->def)
|
||||
continue;
|
||||
q->label = c->label;
|
||||
if(isv)
|
||||
q->val = c->val;
|
||||
else
|
||||
q->val = (int32)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */
|
||||
q++;
|
||||
}
|
||||
qsort(iq, nc, sizeof(C1), swcmp);
|
||||
if(debug['W'])
|
||||
for(i=0; i<nc; i++)
|
||||
print("case %2d: = %.8llux\n", i, (vlong)iq[i].val);
|
||||
for(i=0; i<nc-1; i++)
|
||||
if(iq[i].val == iq[i+1].val)
|
||||
diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
|
||||
if(def == 0) {
|
||||
def = breakpc;
|
||||
nbreak++;
|
||||
}
|
||||
swit1(iq, nc, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
newcase(void)
|
||||
{
|
||||
Case *c;
|
||||
|
||||
c = alloc(sizeof(*c));
|
||||
c->link = cases;
|
||||
cases = c;
|
||||
}
|
||||
|
||||
int32
|
||||
outlstring(TRune *s, int32 n)
|
||||
{
|
||||
char buf[sizeof(TRune)];
|
||||
uint c;
|
||||
int i;
|
||||
int32 r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
while(nstring & (sizeof(TRune)-1))
|
||||
outstring("", 1);
|
||||
r = nstring;
|
||||
while(n > 0) {
|
||||
c = *s++;
|
||||
if(align(0, types[TCHAR], Aarg1, nil)) {
|
||||
for(i = 0; i < sizeof(TRune); i++)
|
||||
buf[i] = c>>(8*(sizeof(TRune) - i - 1));
|
||||
} else {
|
||||
for(i = 0; i < sizeof(TRune); i++)
|
||||
buf[i] = c>>(8*i);
|
||||
}
|
||||
outstring(buf, sizeof(TRune));
|
||||
n -= sizeof(TRune);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
nullwarn(Node *l, Node *r)
|
||||
{
|
||||
warn(Z, "result of operation not used");
|
||||
if(l != Z)
|
||||
cgen(l, Z);
|
||||
if(r != Z)
|
||||
cgen(r, Z);
|
||||
}
|
@ -1,640 +0,0 @@
|
||||
// Inferno utils/cc/scon.c
|
||||
// http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.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 "cc.h"
|
||||
|
||||
static Node*
|
||||
acast(Type *t, Node *n)
|
||||
{
|
||||
if(n->type->etype != t->etype || n->op == OBIT) {
|
||||
n = new1(OCAST, n, Z);
|
||||
if(nocast(n->left->type, t))
|
||||
*n = *n->left;
|
||||
n->type = t;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
evconst(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int et, isf;
|
||||
vlong v;
|
||||
double d;
|
||||
|
||||
if(n == Z || n->type == T)
|
||||
return;
|
||||
|
||||
et = n->type->etype;
|
||||
isf = typefd[et];
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
|
||||
d = 0;
|
||||
v = 0;
|
||||
|
||||
switch(n->op) {
|
||||
default:
|
||||
return;
|
||||
|
||||
case ONEG:
|
||||
if(isf)
|
||||
d = -l->fconst;
|
||||
else
|
||||
v = -l->vconst;
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
v = ~l->vconst;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(et == TVOID)
|
||||
return;
|
||||
et = l->type->etype;
|
||||
if(isf) {
|
||||
if(typefd[et])
|
||||
d = l->fconst;
|
||||
else
|
||||
d = l->vconst;
|
||||
} else {
|
||||
if(typefd[et])
|
||||
v = l->fconst;
|
||||
else
|
||||
v = convvtox(l->vconst, n->type->etype);
|
||||
}
|
||||
break;
|
||||
|
||||
case OCONST:
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
if(isf)
|
||||
d = l->fconst + r->fconst;
|
||||
else {
|
||||
v = l->vconst + r->vconst;
|
||||
}
|
||||
break;
|
||||
|
||||
case OSUB:
|
||||
if(isf)
|
||||
d = l->fconst - r->fconst;
|
||||
else
|
||||
v = l->vconst - r->vconst;
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
if(isf)
|
||||
d = l->fconst * r->fconst;
|
||||
else {
|
||||
v = l->vconst * r->vconst;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMUL:
|
||||
v = (uvlong)l->vconst * (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
|
||||
case ODIV:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "divide by zero");
|
||||
return;
|
||||
}
|
||||
if(isf)
|
||||
d = l->fconst / r->fconst;
|
||||
else
|
||||
v = l->vconst / r->vconst;
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "divide by zero");
|
||||
return;
|
||||
}
|
||||
v = (uvlong)l->vconst / (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OMOD:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "modulo by zero");
|
||||
return;
|
||||
}
|
||||
v = l->vconst % r->vconst;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
if(vconst(r) == 0) {
|
||||
warn(n, "modulo by zero");
|
||||
return;
|
||||
}
|
||||
v = (uvlong)l->vconst % (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OAND:
|
||||
v = l->vconst & r->vconst;
|
||||
break;
|
||||
|
||||
case OOR:
|
||||
v = l->vconst | r->vconst;
|
||||
break;
|
||||
|
||||
case OXOR:
|
||||
v = l->vconst ^ r->vconst;
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
if(l->type->width != sizeof(uvlong))
|
||||
v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
|
||||
else
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHR:
|
||||
v = l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
v = (uvlong)l->vconst << r->vconst;
|
||||
break;
|
||||
|
||||
case OLO:
|
||||
v = (uvlong)l->vconst < (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OLT:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst < r->fconst;
|
||||
else
|
||||
v = l->vconst < r->vconst;
|
||||
break;
|
||||
|
||||
case OHI:
|
||||
v = (uvlong)l->vconst > (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OGT:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst > r->fconst;
|
||||
else
|
||||
v = l->vconst > r->vconst;
|
||||
break;
|
||||
|
||||
case OLS:
|
||||
v = (uvlong)l->vconst <= (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OLE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst <= r->fconst;
|
||||
else
|
||||
v = l->vconst <= r->vconst;
|
||||
break;
|
||||
|
||||
case OHS:
|
||||
v = (uvlong)l->vconst >= (uvlong)r->vconst;
|
||||
break;
|
||||
|
||||
case OGE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst >= r->fconst;
|
||||
else
|
||||
v = l->vconst >= r->vconst;
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst == r->fconst;
|
||||
else
|
||||
v = l->vconst == r->vconst;
|
||||
break;
|
||||
|
||||
case ONE:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst != r->fconst;
|
||||
else
|
||||
v = l->vconst != r->vconst;
|
||||
break;
|
||||
|
||||
case ONOT:
|
||||
if(typefd[l->type->etype])
|
||||
v = !l->fconst;
|
||||
else
|
||||
v = !l->vconst;
|
||||
break;
|
||||
|
||||
case OANDAND:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst && r->fconst;
|
||||
else
|
||||
v = l->vconst && r->vconst;
|
||||
break;
|
||||
|
||||
case OOROR:
|
||||
if(typefd[l->type->etype])
|
||||
v = l->fconst || r->fconst;
|
||||
else
|
||||
v = l->vconst || r->vconst;
|
||||
break;
|
||||
}
|
||||
if(isf) {
|
||||
n->fconst = d;
|
||||
} else {
|
||||
n->vconst = convvtox(v, n->type->etype);
|
||||
}
|
||||
n->oldop = n->op;
|
||||
n->op = OCONST;
|
||||
}
|
||||
|
||||
void
|
||||
acom(Node *n)
|
||||
{
|
||||
Type *t;
|
||||
Node *l, *r;
|
||||
int i;
|
||||
|
||||
switch(n->op)
|
||||
{
|
||||
|
||||
case ONAME:
|
||||
case OCONST:
|
||||
case OSTRING:
|
||||
case OINDREG:
|
||||
case OREGISTER:
|
||||
return;
|
||||
|
||||
case ONEG:
|
||||
l = n->left;
|
||||
if(addo(n) && addo(l))
|
||||
break;
|
||||
acom(l);
|
||||
return;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OMUL:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(addo(n)) {
|
||||
if(addo(r))
|
||||
break;
|
||||
if(addo(l))
|
||||
break;
|
||||
}
|
||||
acom(l);
|
||||
acom(r);
|
||||
return;
|
||||
|
||||
default:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l != Z)
|
||||
acom(l);
|
||||
if(r != Z)
|
||||
acom(r);
|
||||
return;
|
||||
}
|
||||
|
||||
/* bust terms out */
|
||||
t = n->type;
|
||||
term[0].mult = 0;
|
||||
term[0].node = Z;
|
||||
nterm = 1;
|
||||
acom1(1, n);
|
||||
if(debug['m'])
|
||||
for(i=0; i<nterm; i++) {
|
||||
print("%d %3lld ", i, term[i].mult);
|
||||
prtree1(term[i].node, 1, 0);
|
||||
}
|
||||
if(nterm < NTERM)
|
||||
acom2(n, t);
|
||||
n->type = t;
|
||||
}
|
||||
|
||||
int
|
||||
acomcmp1(const void *a1, const void *a2)
|
||||
{
|
||||
vlong c1, c2;
|
||||
Term *t1, *t2;
|
||||
|
||||
t1 = (Term*)a1;
|
||||
t2 = (Term*)a2;
|
||||
c1 = t1->mult;
|
||||
if(c1 < 0)
|
||||
c1 = -c1;
|
||||
c2 = t2->mult;
|
||||
if(c2 < 0)
|
||||
c2 = -c2;
|
||||
if(c1 > c2)
|
||||
return 1;
|
||||
if(c1 < c2)
|
||||
return -1;
|
||||
c1 = 1;
|
||||
if(t1->mult < 0)
|
||||
c1 = 0;
|
||||
c2 = 1;
|
||||
if(t2->mult < 0)
|
||||
c2 = 0;
|
||||
if(c2 -= c1)
|
||||
return c2;
|
||||
if(t2 > t1)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
acomcmp2(const void *a1, const void *a2)
|
||||
{
|
||||
vlong c1, c2;
|
||||
Term *t1, *t2;
|
||||
|
||||
t1 = (Term*)a1;
|
||||
t2 = (Term*)a2;
|
||||
c1 = t1->mult;
|
||||
c2 = t2->mult;
|
||||
if(c1 > c2)
|
||||
return 1;
|
||||
if(c1 < c2)
|
||||
return -1;
|
||||
if(t2 > t1)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
acom2(Node *n, Type *t)
|
||||
{
|
||||
Node *l, *r;
|
||||
Term trm[NTERM];
|
||||
int et, nt, i, j;
|
||||
vlong c1, c2;
|
||||
|
||||
/*
|
||||
* copy into automatic
|
||||
*/
|
||||
c2 = 0;
|
||||
nt = nterm;
|
||||
for(i=0; i<nt; i++)
|
||||
trm[i] = term[i];
|
||||
/*
|
||||
* recur on subtrees
|
||||
*/
|
||||
j = 0;
|
||||
for(i=1; i<nt; i++) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 == 0)
|
||||
continue;
|
||||
l = trm[i].node;
|
||||
if(l != Z) {
|
||||
j = 1;
|
||||
acom(l);
|
||||
}
|
||||
}
|
||||
c1 = trm[0].mult;
|
||||
if(j == 0) {
|
||||
n->oldop = n->op;
|
||||
n->op = OCONST;
|
||||
n->vconst = c1;
|
||||
return;
|
||||
}
|
||||
et = t->etype;
|
||||
|
||||
/*
|
||||
* prepare constant term,
|
||||
* combine it with an addressing term
|
||||
*/
|
||||
if(c1 != 0) {
|
||||
l = new1(OCONST, Z, Z);
|
||||
l->type = t;
|
||||
l->vconst = c1;
|
||||
trm[0].mult = 1;
|
||||
for(i=1; i<nt; i++) {
|
||||
if(trm[i].mult != 1)
|
||||
continue;
|
||||
r = trm[i].node;
|
||||
if(r->op != OADDR)
|
||||
continue;
|
||||
r->type = t;
|
||||
l = new1(OADD, r, l);
|
||||
l->type = t;
|
||||
trm[i].mult = 0;
|
||||
break;
|
||||
}
|
||||
trm[0].node = l;
|
||||
}
|
||||
/*
|
||||
* look for factorable terms
|
||||
* c1*i + c1*c2*j -> c1*(i + c2*j)
|
||||
*/
|
||||
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
|
||||
for(i=nt-1; i>=0; i--) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 < 0)
|
||||
c1 = -c1;
|
||||
if(c1 <= 1)
|
||||
continue;
|
||||
for(j=i+1; j<nt; j++) {
|
||||
c2 = trm[j].mult;
|
||||
if(c2 < 0)
|
||||
c2 = -c2;
|
||||
if(c2 <= 1)
|
||||
continue;
|
||||
if(c2 % c1)
|
||||
continue;
|
||||
r = trm[j].node;
|
||||
if(r->type->etype != et)
|
||||
r = acast(t, r);
|
||||
c2 = trm[j].mult/trm[i].mult;
|
||||
if(c2 != 1 && c2 != -1) {
|
||||
r = new1(OMUL, r, new(OCONST, Z, Z));
|
||||
r->type = t;
|
||||
r->right->type = t;
|
||||
r->right->vconst = c2;
|
||||
}
|
||||
l = trm[i].node;
|
||||
if(l->type->etype != et)
|
||||
l = acast(t, l);
|
||||
r = new1(OADD, l, r);
|
||||
r->type = t;
|
||||
if(c2 == -1)
|
||||
r->op = OSUB;
|
||||
trm[i].node = r;
|
||||
trm[j].mult = 0;
|
||||
}
|
||||
}
|
||||
if(debug['m']) {
|
||||
print("\n");
|
||||
for(i=0; i<nt; i++) {
|
||||
print("%d %3lld ", i, trm[i].mult);
|
||||
prtree1(trm[i].node, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* put it all back together
|
||||
*/
|
||||
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
|
||||
l = Z;
|
||||
for(i=nt-1; i>=0; i--) {
|
||||
c1 = trm[i].mult;
|
||||
if(c1 == 0)
|
||||
continue;
|
||||
r = trm[i].node;
|
||||
if(r->type->etype != et || r->op == OBIT)
|
||||
r = acast(t, r);
|
||||
if(c1 != 1 && c1 != -1) {
|
||||
r = new1(OMUL, r, new(OCONST, Z, Z));
|
||||
r->type = t;
|
||||
r->right->type = t;
|
||||
if(c1 < 0) {
|
||||
r->right->vconst = -c1;
|
||||
c1 = -1;
|
||||
} else {
|
||||
r->right->vconst = c1;
|
||||
c1 = 1;
|
||||
}
|
||||
}
|
||||
if(l == Z) {
|
||||
l = r;
|
||||
c2 = c1;
|
||||
continue;
|
||||
}
|
||||
if(c1 < 0)
|
||||
if(c2 < 0)
|
||||
l = new1(OADD, l, r);
|
||||
else
|
||||
l = new1(OSUB, l, r);
|
||||
else
|
||||
if(c2 < 0) {
|
||||
l = new1(OSUB, r, l);
|
||||
c2 = 1;
|
||||
} else
|
||||
l = new1(OADD, l, r);
|
||||
l->type = t;
|
||||
}
|
||||
if(c2 < 0) {
|
||||
r = new1(OCONST, 0, 0);
|
||||
r->vconst = 0;
|
||||
r->type = t;
|
||||
l = new1(OSUB, r, l);
|
||||
l->type = t;
|
||||
}
|
||||
*n = *l;
|
||||
}
|
||||
|
||||
void
|
||||
acom1(vlong v, Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(v == 0 || nterm >= NTERM)
|
||||
return;
|
||||
if(!addo(n)) {
|
||||
if(n->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
term[0].mult += v*n->vconst;
|
||||
return;
|
||||
}
|
||||
term[nterm].mult = v;
|
||||
term[nterm].node = n;
|
||||
nterm++;
|
||||
return;
|
||||
}
|
||||
switch(n->op) {
|
||||
|
||||
case OCAST:
|
||||
acom1(v, n->left);
|
||||
break;
|
||||
|
||||
case ONEG:
|
||||
acom1(-v, n->left);
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
acom1(v, n->left);
|
||||
acom1(v, n->right);
|
||||
break;
|
||||
|
||||
case OSUB:
|
||||
acom1(v, n->left);
|
||||
acom1(-v, n->right);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
acom1(v*l->vconst, r);
|
||||
break;
|
||||
}
|
||||
if(r->op == OCONST)
|
||||
if(!typefd[n->type->etype]) {
|
||||
acom1(v*r->vconst, l);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
diag(n, "not addo");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
addo(Node *n)
|
||||
{
|
||||
|
||||
if(n != Z)
|
||||
if(!typefd[n->type->etype])
|
||||
if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
|
||||
switch(n->op) {
|
||||
|
||||
case OCAST:
|
||||
if(nilcast(n->left->type, n->type))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OSUB:
|
||||
return 1;
|
||||
|
||||
case OMUL:
|
||||
if(n->left->op == OCONST)
|
||||
return 1;
|
||||
if(n->right->op == OCONST)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
2068
src/cmd/cc/sub.c
2068
src/cmd/cc/sub.c
File diff suppressed because it is too large
Load Diff
3822
src/cmd/cc/y.tab.c
3822
src/cmd/cc/y.tab.c
File diff suppressed because it is too large
Load Diff
@ -1,230 +0,0 @@
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
LORE = 258,
|
||||
LXORE = 259,
|
||||
LANDE = 260,
|
||||
LLSHE = 261,
|
||||
LRSHE = 262,
|
||||
LMDE = 263,
|
||||
LDVE = 264,
|
||||
LMLE = 265,
|
||||
LME = 266,
|
||||
LPE = 267,
|
||||
LOROR = 268,
|
||||
LANDAND = 269,
|
||||
LNE = 270,
|
||||
LEQ = 271,
|
||||
LGE = 272,
|
||||
LLE = 273,
|
||||
LRSH = 274,
|
||||
LLSH = 275,
|
||||
LMG = 276,
|
||||
LPP = 277,
|
||||
LMM = 278,
|
||||
LNAME = 279,
|
||||
LTYPE = 280,
|
||||
LFCONST = 281,
|
||||
LDCONST = 282,
|
||||
LCONST = 283,
|
||||
LLCONST = 284,
|
||||
LUCONST = 285,
|
||||
LULCONST = 286,
|
||||
LVLCONST = 287,
|
||||
LUVLCONST = 288,
|
||||
LSTRING = 289,
|
||||
LLSTRING = 290,
|
||||
LAUTO = 291,
|
||||
LBREAK = 292,
|
||||
LCASE = 293,
|
||||
LCHAR = 294,
|
||||
LCONTINUE = 295,
|
||||
LDEFAULT = 296,
|
||||
LDO = 297,
|
||||
LDOUBLE = 298,
|
||||
LELSE = 299,
|
||||
LEXTERN = 300,
|
||||
LFLOAT = 301,
|
||||
LFOR = 302,
|
||||
LGOTO = 303,
|
||||
LIF = 304,
|
||||
LINT = 305,
|
||||
LLONG = 306,
|
||||
LPREFETCH = 307,
|
||||
LREGISTER = 308,
|
||||
LRETURN = 309,
|
||||
LSHORT = 310,
|
||||
LSIZEOF = 311,
|
||||
LUSED = 312,
|
||||
LSTATIC = 313,
|
||||
LSTRUCT = 314,
|
||||
LSWITCH = 315,
|
||||
LTYPEDEF = 316,
|
||||
LTYPESTR = 317,
|
||||
LUNION = 318,
|
||||
LUNSIGNED = 319,
|
||||
LWHILE = 320,
|
||||
LVOID = 321,
|
||||
LENUM = 322,
|
||||
LSIGNED = 323,
|
||||
LCONSTNT = 324,
|
||||
LVOLATILE = 325,
|
||||
LSET = 326,
|
||||
LSIGNOF = 327,
|
||||
LRESTRICT = 328,
|
||||
LINLINE = 329
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define LORE 258
|
||||
#define LXORE 259
|
||||
#define LANDE 260
|
||||
#define LLSHE 261
|
||||
#define LRSHE 262
|
||||
#define LMDE 263
|
||||
#define LDVE 264
|
||||
#define LMLE 265
|
||||
#define LME 266
|
||||
#define LPE 267
|
||||
#define LOROR 268
|
||||
#define LANDAND 269
|
||||
#define LNE 270
|
||||
#define LEQ 271
|
||||
#define LGE 272
|
||||
#define LLE 273
|
||||
#define LRSH 274
|
||||
#define LLSH 275
|
||||
#define LMG 276
|
||||
#define LPP 277
|
||||
#define LMM 278
|
||||
#define LNAME 279
|
||||
#define LTYPE 280
|
||||
#define LFCONST 281
|
||||
#define LDCONST 282
|
||||
#define LCONST 283
|
||||
#define LLCONST 284
|
||||
#define LUCONST 285
|
||||
#define LULCONST 286
|
||||
#define LVLCONST 287
|
||||
#define LUVLCONST 288
|
||||
#define LSTRING 289
|
||||
#define LLSTRING 290
|
||||
#define LAUTO 291
|
||||
#define LBREAK 292
|
||||
#define LCASE 293
|
||||
#define LCHAR 294
|
||||
#define LCONTINUE 295
|
||||
#define LDEFAULT 296
|
||||
#define LDO 297
|
||||
#define LDOUBLE 298
|
||||
#define LELSE 299
|
||||
#define LEXTERN 300
|
||||
#define LFLOAT 301
|
||||
#define LFOR 302
|
||||
#define LGOTO 303
|
||||
#define LIF 304
|
||||
#define LINT 305
|
||||
#define LLONG 306
|
||||
#define LPREFETCH 307
|
||||
#define LREGISTER 308
|
||||
#define LRETURN 309
|
||||
#define LSHORT 310
|
||||
#define LSIZEOF 311
|
||||
#define LUSED 312
|
||||
#define LSTATIC 313
|
||||
#define LSTRUCT 314
|
||||
#define LSWITCH 315
|
||||
#define LTYPEDEF 316
|
||||
#define LTYPESTR 317
|
||||
#define LUNION 318
|
||||
#define LUNSIGNED 319
|
||||
#define LWHILE 320
|
||||
#define LVOID 321
|
||||
#define LENUM 322
|
||||
#define LSIGNED 323
|
||||
#define LCONSTNT 324
|
||||
#define LVOLATILE 325
|
||||
#define LSET 326
|
||||
#define LSIGNOF 327
|
||||
#define LRESTRICT 328
|
||||
#define LINLINE 329
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 36 "cc.y"
|
||||
{
|
||||
Node* node;
|
||||
Sym* sym;
|
||||
Type* type;
|
||||
struct
|
||||
{
|
||||
Type* t;
|
||||
uchar c;
|
||||
} tycl;
|
||||
struct
|
||||
{
|
||||
Type* t1;
|
||||
Type* t2;
|
||||
Type* t3;
|
||||
uchar c;
|
||||
} tyty;
|
||||
struct
|
||||
{
|
||||
char* s;
|
||||
int32 l;
|
||||
} sval;
|
||||
int32 lval;
|
||||
double dval;
|
||||
vlong vval;
|
||||
}
|
||||
/* Line 1529 of yacc.c. */
|
||||
#line 223 "y.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
@ -155,6 +155,7 @@ var fset = token.NewFileSet()
|
||||
|
||||
var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
|
||||
var dynout = flag.String("dynout", "", "write -dynobj output to this file")
|
||||
var dynpackage = flag.String("dynpackage", "main", "set Go package for dynobj output")
|
||||
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
|
||||
|
||||
// These flags are for bootstrapping a new Go implementation,
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -23,8 +24,15 @@ var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
|
||||
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
|
||||
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
|
||||
func (p *Package) writeDefs() {
|
||||
fgo2 := creat(*objDir + "_cgo_gotypes.go")
|
||||
fc := creat(*objDir + "_cgo_defun.c")
|
||||
var fgo2, fc io.Writer
|
||||
f := creat(*objDir + "_cgo_gotypes.go")
|
||||
defer f.Close()
|
||||
fgo2 = f
|
||||
if *gccgo {
|
||||
f := creat(*objDir + "_cgo_defun.c")
|
||||
defer f.Close()
|
||||
fc = f
|
||||
}
|
||||
fm := creat(*objDir + "_cgo_main.c")
|
||||
|
||||
var gccgoInit bytes.Buffer
|
||||
@ -34,7 +42,7 @@ func (p *Package) writeDefs() {
|
||||
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
|
||||
if k == "LDFLAGS" && !*gccgo {
|
||||
for _, arg := range v {
|
||||
fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
|
||||
fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +96,6 @@ func (p *Package) writeDefs() {
|
||||
if *gccgo {
|
||||
fmt.Fprint(fc, p.cPrologGccgo())
|
||||
} else {
|
||||
fmt.Fprint(fc, cProlog)
|
||||
fmt.Fprint(fgo2, goProlog)
|
||||
}
|
||||
|
||||
@ -104,42 +111,42 @@ func (p *Package) writeDefs() {
|
||||
if !cVars[n.C] {
|
||||
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
|
||||
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
|
||||
|
||||
if !*gccgo {
|
||||
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
|
||||
if *gccgo {
|
||||
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
|
||||
} else {
|
||||
fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
|
||||
fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
|
||||
fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
|
||||
}
|
||||
|
||||
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
|
||||
|
||||
cVars[n.C] = true
|
||||
}
|
||||
var amp string
|
||||
|
||||
var node ast.Node
|
||||
if n.Kind == "var" {
|
||||
amp = "&"
|
||||
node = &ast.StarExpr{X: n.Type.Go}
|
||||
} else if n.Kind == "fpvar" {
|
||||
node = n.Type.Go
|
||||
if *gccgo {
|
||||
amp = "&"
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Errorf("invalid var kind %q", n.Kind))
|
||||
}
|
||||
if *gccgo {
|
||||
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
|
||||
fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
|
||||
} else {
|
||||
fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
|
||||
fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
|
||||
fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
|
||||
fmt.Fprintf(fc, "\n")
|
||||
}
|
||||
fmt.Fprintf(fc, "\n")
|
||||
|
||||
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
|
||||
conf.Fprint(fgo2, fset, node)
|
||||
if !*gccgo {
|
||||
fmt.Fprintf(fgo2, " = (")
|
||||
conf.Fprint(fgo2, fset, node)
|
||||
fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\n")
|
||||
}
|
||||
fmt.Fprintf(fc, "\n")
|
||||
if *gccgo {
|
||||
fmt.Fprintf(fc, "\n")
|
||||
}
|
||||
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
@ -169,9 +176,6 @@ func (p *Package) writeDefs() {
|
||||
fmt.Fprint(fc, init)
|
||||
fmt.Fprintln(fc, "}")
|
||||
}
|
||||
|
||||
fgo2.Close()
|
||||
fc.Close()
|
||||
}
|
||||
|
||||
func dynimport(obj string) {
|
||||
@ -184,13 +188,15 @@ func dynimport(obj string) {
|
||||
stdout = f
|
||||
}
|
||||
|
||||
fmt.Fprintf(stdout, "package %s\n", *dynpackage)
|
||||
|
||||
if f, err := elf.Open(obj); err == nil {
|
||||
if *dynlinker {
|
||||
// Emit the cgo_dynamic_linker line.
|
||||
if sec := f.Section(".interp"); sec != nil {
|
||||
if data, err := sec.Data(); err == nil && len(data) > 1 {
|
||||
// skip trailing \0 in data
|
||||
fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
|
||||
fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -203,14 +209,14 @@ func dynimport(obj string) {
|
||||
if s.Version != "" {
|
||||
targ += "#" + s.Version
|
||||
}
|
||||
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
|
||||
}
|
||||
for _, l := range lib {
|
||||
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -224,14 +230,14 @@ func dynimport(obj string) {
|
||||
if len(s) > 0 && s[0] == '_' {
|
||||
s = s[1:]
|
||||
}
|
||||
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
if err != nil {
|
||||
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
|
||||
}
|
||||
for _, l := range lib {
|
||||
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -244,7 +250,7 @@ func dynimport(obj string) {
|
||||
for _, s := range sym {
|
||||
ss := strings.Split(s, ":")
|
||||
name := strings.Split(ss[0], "@")[0]
|
||||
fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -304,7 +310,7 @@ func (p *Package) structType(n *Name) (string, int64) {
|
||||
return buf.String(), off
|
||||
}
|
||||
|
||||
func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
|
||||
func (p *Package) writeDefsFunc(fc, fgo2 io.Writer, n *Name) {
|
||||
name := n.Go
|
||||
gtype := n.FuncType.Go
|
||||
void := gtype.Results == nil || len(gtype.Results.List) == 0
|
||||
@ -397,10 +403,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
|
||||
}
|
||||
|
||||
// C wrapper calls into gcc, passing a pointer to the argument frame.
|
||||
fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
|
||||
fmt.Fprintf(fc, "void %s(void*);\n", cname)
|
||||
fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
|
||||
fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
|
||||
fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
|
||||
fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
|
||||
fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
|
||||
fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
|
||||
|
||||
nret := 0
|
||||
if !void {
|
||||
@ -412,7 +418,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
|
||||
}
|
||||
|
||||
fmt.Fprint(fgo2, "\n")
|
||||
fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
|
||||
conf.Fprint(fgo2, fset, d)
|
||||
fmt.Fprint(fgo2, " {\n")
|
||||
|
||||
@ -626,7 +631,7 @@ func (p *Package) packedAttribute() string {
|
||||
|
||||
// Write out the various stubs we need to support functions exported
|
||||
// from Go so that they are callable from C.
|
||||
func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
||||
func (p *Package) writeExports(fgo2, fc, fm io.Writer) {
|
||||
fgcc := creat(*objDir + "_cgo_export.c")
|
||||
fgcch := creat(*objDir + "_cgo_export.h")
|
||||
|
||||
@ -763,15 +768,15 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
||||
if fn.Recv != nil {
|
||||
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
|
||||
}
|
||||
fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
|
||||
fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
|
||||
fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
|
||||
fmt.Fprintf(fc, "void\n")
|
||||
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fc, "{\n")
|
||||
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
|
||||
fmt.Fprintf(fc, "}\n")
|
||||
fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
|
||||
fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
|
||||
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
|
||||
// The indirect here is converting from a Go function pointer to a C function pointer.
|
||||
fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
|
||||
fmt.Fprintf(fgo2, "}\n")
|
||||
|
||||
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
|
||||
|
||||
@ -817,7 +822,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
|
||||
}
|
||||
|
||||
// Write out the C header allowing C code to call exported gccgo functions.
|
||||
func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
|
||||
func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) {
|
||||
fgcc := creat(*objDir + "_cgo_export.c")
|
||||
fgcch := creat(*objDir + "_cgo_export.h")
|
||||
|
||||
@ -1164,60 +1169,39 @@ char *CString(_GoString_);
|
||||
void *_CMalloc(size_t);
|
||||
`
|
||||
|
||||
const cProlog = `
|
||||
#include "runtime.h"
|
||||
#include "cgocall.h"
|
||||
#include "textflag.h"
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
static void *cgocall_errno = runtime·cgocall_errno;
|
||||
#pragma dataflag NOPTR
|
||||
void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
static void *runtime_gostring = runtime·gostring;
|
||||
#pragma dataflag NOPTR
|
||||
void *·_cgo_runtime_gostring = &runtime_gostring;
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
static void *runtime_gostringn = runtime·gostringn;
|
||||
#pragma dataflag NOPTR
|
||||
void *·_cgo_runtime_gostringn = &runtime_gostringn;
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
static void *runtime_gobytes = runtime·gobytes;
|
||||
#pragma dataflag NOPTR
|
||||
void *·_cgo_runtime_gobytes = &runtime_gobytes;
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
static void *runtime_cmalloc = runtime·cmalloc;
|
||||
#pragma dataflag NOPTR
|
||||
void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
|
||||
|
||||
void ·_Cerrno(void*, int32);
|
||||
`
|
||||
|
||||
const goProlog = `
|
||||
var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
|
||||
var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
|
||||
//go:linkname _cgo_runtime_cgocall_errno runtime.cgocall_errno
|
||||
func _cgo_runtime_cgocall_errno(unsafe.Pointer, uintptr) int32
|
||||
|
||||
//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
|
||||
func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
|
||||
|
||||
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
|
||||
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
|
||||
`
|
||||
|
||||
const goStringDef = `
|
||||
var _cgo_runtime_gostring func(*_Ctype_char) string
|
||||
//go:linkname _cgo_runtime_gostring runtime.gostring
|
||||
func _cgo_runtime_gostring(*_Ctype_char) string
|
||||
|
||||
func _Cfunc_GoString(p *_Ctype_char) string {
|
||||
return _cgo_runtime_gostring(p)
|
||||
}
|
||||
`
|
||||
|
||||
const goStringNDef = `
|
||||
var _cgo_runtime_gostringn func(*_Ctype_char, int) string
|
||||
//go:linkname _cgo_runtime_gostringn runtime.gostringn
|
||||
func _cgo_runtime_gostringn(*_Ctype_char, int) string
|
||||
|
||||
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
|
||||
return _cgo_runtime_gostringn(p, int(l))
|
||||
}
|
||||
`
|
||||
|
||||
const goBytesDef = `
|
||||
var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
|
||||
//go:linkname _cgo_runtime_gobytes runtime.gobytes
|
||||
func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
|
||||
|
||||
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
|
||||
return _cgo_runtime_gobytes(p, int(l))
|
||||
}
|
||||
|
146
src/cmd/dist/build.c
vendored
146
src/cmd/dist/build.c
vendored
@ -526,10 +526,6 @@ static struct {
|
||||
"anames8.c",
|
||||
"anames9.c",
|
||||
}},
|
||||
{"cmd/cc", {
|
||||
"-pgen.c",
|
||||
"-pswt.c",
|
||||
}},
|
||||
{"cmd/gc", {
|
||||
"-cplx.c",
|
||||
"-pgen.c",
|
||||
@ -538,26 +534,6 @@ static struct {
|
||||
"-y1.tab.c", // makefile dreg
|
||||
"opnames.h",
|
||||
}},
|
||||
{"cmd/5c", {
|
||||
"../cc/pgen.c",
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/6c", {
|
||||
"../cc/pgen.c",
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/8c", {
|
||||
"../cc/pgen.c",
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/9c", {
|
||||
"../cc/pgen.c",
|
||||
"../cc/pswt.c",
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
|
||||
}},
|
||||
{"cmd/5g", {
|
||||
"../gc/cplx.c",
|
||||
"../gc/pgen.c",
|
||||
@ -611,12 +587,10 @@ static struct {
|
||||
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a",
|
||||
}},
|
||||
{"runtime", {
|
||||
"zaexperiment.h", // must sort above zasm
|
||||
"zasm_$GOOS_$GOARCH.h",
|
||||
"zaexperiment.h",
|
||||
"zsys_$GOOS_$GOARCH.s",
|
||||
"zgoarch_$GOARCH.go",
|
||||
"zgoos_$GOOS.go",
|
||||
"zruntime_defs_$GOOS_$GOARCH.go",
|
||||
"zversion.go",
|
||||
}},
|
||||
};
|
||||
@ -639,12 +613,10 @@ static struct {
|
||||
{"anames6.c", mkanames},
|
||||
{"anames8.c", mkanames},
|
||||
{"anames9.c", mkanames},
|
||||
{"zasm_", mkzasm},
|
||||
{"zdefaultcc.go", mkzdefaultcc},
|
||||
{"zsys_", mkzsys},
|
||||
{"zgoarch_", mkzgoarch},
|
||||
{"zgoos_", mkzgoos},
|
||||
{"zruntime_defs_", mkzruntimedefs},
|
||||
{"zversion.go", mkzversion},
|
||||
{"zaexperiment.h", mkzexperiment},
|
||||
|
||||
@ -659,7 +631,7 @@ install(char *dir)
|
||||
{
|
||||
char *name, *p, *elem, *prefix, *exe;
|
||||
bool islib, ispkg, isgo, stale, ispackcmd;
|
||||
Buf b, b1, path, final_path, final_name;
|
||||
Buf b, b1, path, final_path, final_name, archive;
|
||||
Vec compile, files, link, go, missing, clean, lib, extra;
|
||||
Time ttarg, t;
|
||||
int i, j, k, n, doclean, targ;
|
||||
@ -676,6 +648,7 @@ install(char *dir)
|
||||
binit(&path);
|
||||
binit(&final_path);
|
||||
binit(&final_name);
|
||||
binit(&archive);
|
||||
vinit(&compile);
|
||||
vinit(&files);
|
||||
vinit(&link);
|
||||
@ -719,7 +692,7 @@ install(char *dir)
|
||||
splitfields(&ldargs, bstr(&b));
|
||||
}
|
||||
|
||||
islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
|
||||
islib = hasprefix(dir, "lib") || streq(dir, "cmd/gc");
|
||||
ispkg = !islib && !hasprefix(dir, "cmd/");
|
||||
isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
|
||||
|
||||
@ -898,17 +871,6 @@ install(char *dir)
|
||||
|
||||
// For package runtime, copy some files into the work space.
|
||||
if(streq(dir, "runtime")) {
|
||||
copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
|
||||
bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
|
||||
copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
|
||||
bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
|
||||
p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
|
||||
if(isfile(p))
|
||||
copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
|
||||
copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
|
||||
bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
|
||||
copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
|
||||
bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
|
||||
copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
|
||||
bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
|
||||
copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
|
||||
@ -942,14 +904,6 @@ install(char *dir)
|
||||
built:;
|
||||
}
|
||||
|
||||
// One more copy for package runtime.
|
||||
// The last batch was required for the generators.
|
||||
// This one is generated.
|
||||
if(streq(dir, "runtime")) {
|
||||
copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
|
||||
bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
|
||||
}
|
||||
|
||||
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
|
||||
// We've generated the right files; the go command can do the build.
|
||||
if(vflag > 1)
|
||||
@ -957,6 +911,42 @@ install(char *dir)
|
||||
goto nobuild;
|
||||
}
|
||||
|
||||
if(isgo) {
|
||||
// The next loop will compile individual non-Go files.
|
||||
// Hand the Go files to the compiler en masse.
|
||||
// For package runtime, this writes go_asm.h, which
|
||||
// the assembly files will need.
|
||||
vreset(&compile);
|
||||
vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
|
||||
|
||||
bpathf(&b, "%s/_go_.a", workdir);
|
||||
vadd(&compile, "-pack");
|
||||
vadd(&compile, "-o");
|
||||
vadd(&compile, bstr(&b));
|
||||
vadd(&clean, bstr(&b));
|
||||
if(!ispackcmd)
|
||||
vadd(&link, bstr(&b));
|
||||
else
|
||||
bwriteb(&archive, &b);
|
||||
|
||||
vadd(&compile, "-p");
|
||||
if(hasprefix(dir, "cmd/"))
|
||||
vadd(&compile, "main");
|
||||
else
|
||||
vadd(&compile, dir);
|
||||
|
||||
if(streq(dir, "runtime")) {
|
||||
vadd(&compile, "-+");
|
||||
vadd(&compile, "-asmhdr");
|
||||
bpathf(&b1, "%s/go_asm.h", workdir);
|
||||
vadd(&compile, bstr(&b1));
|
||||
}
|
||||
|
||||
vcopy(&compile, go.p, go.len);
|
||||
|
||||
runv(nil, bstr(&path), CheckExit, &compile);
|
||||
}
|
||||
|
||||
// Compile the files.
|
||||
for(i=0; i<files.len; i++) {
|
||||
if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
|
||||
@ -1070,38 +1060,10 @@ install(char *dir)
|
||||
}
|
||||
bgwait();
|
||||
|
||||
if(isgo) {
|
||||
// The last loop was compiling individual files.
|
||||
// Hand the Go files to the compiler en masse.
|
||||
vreset(&compile);
|
||||
vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
|
||||
|
||||
bpathf(&b, "%s/_go_.a", workdir);
|
||||
vadd(&compile, "-pack");
|
||||
vadd(&compile, "-o");
|
||||
vadd(&compile, bstr(&b));
|
||||
vadd(&clean, bstr(&b));
|
||||
if(!ispackcmd)
|
||||
vadd(&link, bstr(&b));
|
||||
|
||||
vadd(&compile, "-p");
|
||||
if(hasprefix(dir, "pkg/"))
|
||||
vadd(&compile, dir+4);
|
||||
else
|
||||
vadd(&compile, "main");
|
||||
|
||||
if(streq(dir, "runtime"))
|
||||
vadd(&compile, "-+");
|
||||
|
||||
vcopy(&compile, go.p, go.len);
|
||||
|
||||
runv(nil, bstr(&path), CheckExit, &compile);
|
||||
|
||||
if(ispackcmd) {
|
||||
xremove(link.p[targ]);
|
||||
dopack(link.p[targ], bstr(&b), &link.p[targ+1], link.len - (targ+1));
|
||||
goto nobuild;
|
||||
}
|
||||
if(isgo && ispackcmd) {
|
||||
xremove(link.p[targ]);
|
||||
dopack(link.p[targ], bstr(&archive), &link.p[targ+1], link.len - (targ+1));
|
||||
goto nobuild;
|
||||
}
|
||||
|
||||
if(!islib && !isgo) {
|
||||
@ -1115,17 +1077,7 @@ install(char *dir)
|
||||
xremove(link.p[targ]);
|
||||
|
||||
runv(nil, nil, CheckExit, &link);
|
||||
|
||||
nobuild:
|
||||
// In package runtime, we install runtime.h and cgocall.h too,
|
||||
// for use by cgo compilation.
|
||||
if(streq(dir, "runtime")) {
|
||||
copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
|
||||
bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0);
|
||||
copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
|
||||
bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0);
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
for(i=0; i<clean.len; i++)
|
||||
@ -1134,6 +1086,7 @@ out:
|
||||
bfree(&b);
|
||||
bfree(&b1);
|
||||
bfree(&path);
|
||||
bfree(&archive);
|
||||
vfree(&compile);
|
||||
vfree(&files);
|
||||
vfree(&link);
|
||||
@ -1321,11 +1274,9 @@ static char *buildorder[] = {
|
||||
"libbio",
|
||||
"liblink",
|
||||
|
||||
"cmd/cc", // must be before c
|
||||
"cmd/gc", // must be before g
|
||||
"cmd/%sl", // must be before a, c, g
|
||||
"cmd/%sl", // must be before a, g
|
||||
"cmd/%sa",
|
||||
"cmd/%sc",
|
||||
"cmd/%sg",
|
||||
|
||||
// The dependency order here was copied from a buildscript
|
||||
@ -1382,22 +1333,17 @@ static char *buildorder[] = {
|
||||
static char *cleantab[] = {
|
||||
// Commands and C libraries.
|
||||
"cmd/5a",
|
||||
"cmd/5c",
|
||||
"cmd/5g",
|
||||
"cmd/5l",
|
||||
"cmd/6a",
|
||||
"cmd/6c",
|
||||
"cmd/6g",
|
||||
"cmd/6l",
|
||||
"cmd/8a",
|
||||
"cmd/8c",
|
||||
"cmd/8g",
|
||||
"cmd/8l",
|
||||
"cmd/9a",
|
||||
"cmd/9c",
|
||||
"cmd/9g",
|
||||
"cmd/9l",
|
||||
"cmd/cc",
|
||||
"cmd/gc",
|
||||
"cmd/go",
|
||||
"lib9",
|
||||
|
306
src/cmd/dist/buildruntime.c
vendored
306
src/cmd/dist/buildruntime.c
vendored
@ -127,174 +127,8 @@ mkzgoos(char *dir, char *file)
|
||||
bfree(&out);
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *goarch;
|
||||
char *goos;
|
||||
char *hdr;
|
||||
} zasmhdr[] = {
|
||||
{"386", "",
|
||||
"#define get_tls(r) MOVL TLS, r\n"
|
||||
"#define g(r) 0(r)(TLS*1)\n"
|
||||
},
|
||||
{"amd64p32", "",
|
||||
"#define get_tls(r) MOVL TLS, r\n"
|
||||
"#define g(r) 0(r)(TLS*1)\n"
|
||||
},
|
||||
{"amd64", "",
|
||||
"#define get_tls(r) MOVQ TLS, r\n"
|
||||
"#define g(r) 0(r)(TLS*1)\n"
|
||||
},
|
||||
|
||||
{"arm", "",
|
||||
"#define LR R14\n"
|
||||
},
|
||||
|
||||
{"power64", "",
|
||||
"#define g R30\n"
|
||||
},
|
||||
{"power64le", "",
|
||||
"#define g R30\n"
|
||||
},
|
||||
};
|
||||
|
||||
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
|
||||
|
||||
// mkzasm writes zasm_$GOOS_$GOARCH.h,
|
||||
// which contains struct offsets for use by
|
||||
// assembly files. It also writes a copy to the work space
|
||||
// under the name zasm_GOOS_GOARCH.h (no expansion).
|
||||
//
|
||||
void
|
||||
mkzasm(char *dir, char *file)
|
||||
{
|
||||
int i, n;
|
||||
char *aggr, *p;
|
||||
Buf in, b, b1, out, exp;
|
||||
Vec argv, lines, fields;
|
||||
|
||||
binit(&in);
|
||||
binit(&b);
|
||||
binit(&b1);
|
||||
binit(&out);
|
||||
binit(&exp);
|
||||
vinit(&argv);
|
||||
vinit(&lines);
|
||||
vinit(&fields);
|
||||
|
||||
bwritestr(&out, "// auto generated by go tool dist\n\n");
|
||||
if(streq(goos, "linux")) {
|
||||
bwritestr(&out, "// +build !android\n\n");
|
||||
}
|
||||
|
||||
for(i=0; i<nelem(zasmhdr); i++) {
|
||||
if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
|
||||
bwritestr(&out, zasmhdr[i].hdr);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
fatal("unknown $GOOS/$GOARCH in mkzasm");
|
||||
ok:
|
||||
|
||||
copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
|
||||
bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
|
||||
|
||||
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
|
||||
// to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
|
||||
// report compilation failures (the -o redirects all messages, unfortunately).
|
||||
vreset(&argv);
|
||||
vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
|
||||
vadd(&argv, "-D");
|
||||
vadd(&argv, bprintf(&b, "GOOS_%s", goos));
|
||||
vadd(&argv, "-D");
|
||||
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
|
||||
vadd(&argv, "-I");
|
||||
vadd(&argv, bprintf(&b, "%s", workdir));
|
||||
vadd(&argv, "-I");
|
||||
vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
|
||||
vadd(&argv, "-n");
|
||||
vadd(&argv, "-a");
|
||||
vadd(&argv, "-o");
|
||||
vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
|
||||
vadd(&argv, "proc.c");
|
||||
runv(nil, dir, CheckExit, &argv);
|
||||
readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
|
||||
|
||||
// Convert input like
|
||||
// aggr G
|
||||
// {
|
||||
// Gobuf 24 sched;
|
||||
// 'Y' 48 stack0;
|
||||
// }
|
||||
// StackMin = 128;
|
||||
// into output like
|
||||
// #define g_sched 24
|
||||
// #define g_stack0 48
|
||||
// #define const_StackMin 128
|
||||
aggr = nil;
|
||||
splitlines(&lines, bstr(&in));
|
||||
for(i=0; i<lines.len; i++) {
|
||||
splitfields(&fields, lines.p[i]);
|
||||
if(fields.len == 2 && streq(fields.p[0], "aggr")) {
|
||||
if(streq(fields.p[1], "G"))
|
||||
aggr = "g";
|
||||
else if(streq(fields.p[1], "M"))
|
||||
aggr = "m";
|
||||
else if(streq(fields.p[1], "P"))
|
||||
aggr = "p";
|
||||
else if(streq(fields.p[1], "Gobuf"))
|
||||
aggr = "gobuf";
|
||||
else if(streq(fields.p[1], "LibCall"))
|
||||
aggr = "libcall";
|
||||
else if(streq(fields.p[1], "WinCallbackContext"))
|
||||
aggr = "cbctxt";
|
||||
else if(streq(fields.p[1], "SEH"))
|
||||
aggr = "seh";
|
||||
else if(streq(fields.p[1], "Alg"))
|
||||
aggr = "alg";
|
||||
else if(streq(fields.p[1], "Panic"))
|
||||
aggr = "panic";
|
||||
else if(streq(fields.p[1], "Stack"))
|
||||
aggr = "stack";
|
||||
}
|
||||
if(hasprefix(lines.p[i], "}"))
|
||||
aggr = nil;
|
||||
if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
|
||||
n = fields.len;
|
||||
p = fields.p[n-1];
|
||||
if(p[xstrlen(p)-1] == ';')
|
||||
p[xstrlen(p)-1] = '\0';
|
||||
bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
|
||||
}
|
||||
if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants
|
||||
p = fields.p[2];
|
||||
if(p[xstrlen(p)-1] == ';')
|
||||
p[xstrlen(p)-1] = '\0';
|
||||
bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p));
|
||||
}
|
||||
}
|
||||
|
||||
// Some #defines that are used for .c files.
|
||||
if(streq(goos, "windows")) {
|
||||
bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB));
|
||||
}
|
||||
|
||||
xgetenv(&exp, "GOEXPERIMENT");
|
||||
bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
|
||||
|
||||
// Write both to file and to workdir/zasm_GOOS_GOARCH.h.
|
||||
writefile(&out, file, 0);
|
||||
writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);
|
||||
|
||||
bfree(&in);
|
||||
bfree(&b);
|
||||
bfree(&b1);
|
||||
bfree(&out);
|
||||
bfree(&exp);
|
||||
vfree(&argv);
|
||||
vfree(&lines);
|
||||
vfree(&fields);
|
||||
}
|
||||
|
||||
// mkzsys writes zsys_$GOOS_$GOARCH.s,
|
||||
// which contains arch or os specific asm code.
|
||||
//
|
||||
@ -333,143 +167,3 @@ mkzsys(char *dir, char *file)
|
||||
|
||||
bfree(&out);
|
||||
}
|
||||
|
||||
static char *runtimedefs[] = {
|
||||
"defs.c",
|
||||
"malloc.c",
|
||||
"mcache.c",
|
||||
"mgc0.c",
|
||||
"proc.c",
|
||||
"parfor.c",
|
||||
"stack.c",
|
||||
};
|
||||
|
||||
// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
|
||||
// which contains Go struct definitions equivalent to the C ones.
|
||||
// Mostly we just write the output of 6c -q to the file.
|
||||
// However, we run it on multiple files, so we have to delete
|
||||
// the duplicated definitions, and we don't care about the funcs,
|
||||
// so we delete those too.
|
||||
//
|
||||
void
|
||||
mkzruntimedefs(char *dir, char *file)
|
||||
{
|
||||
int i, skip;
|
||||
char *p;
|
||||
Buf in, b, b1, out;
|
||||
Vec argv, lines, fields, seen;
|
||||
|
||||
binit(&in);
|
||||
binit(&b);
|
||||
binit(&b1);
|
||||
binit(&out);
|
||||
vinit(&argv);
|
||||
vinit(&lines);
|
||||
vinit(&fields);
|
||||
vinit(&seen);
|
||||
|
||||
bwritestr(&out, "// auto generated by go tool dist\n"
|
||||
"\n");
|
||||
|
||||
if(streq(goos, "linux")) {
|
||||
bwritestr(&out, "// +build !android\n\n");
|
||||
}
|
||||
|
||||
bwritestr(&out,
|
||||
"package runtime\n"
|
||||
"import \"unsafe\"\n"
|
||||
"var _ unsafe.Pointer\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
// Do not emit definitions for these.
|
||||
vadd(&seen, "true");
|
||||
vadd(&seen, "false");
|
||||
vadd(&seen, "raceenabled");
|
||||
vadd(&seen, "allgs");
|
||||
|
||||
// Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
|
||||
// on each of the runtimedefs C files.
|
||||
vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
|
||||
vadd(&argv, "-D");
|
||||
vadd(&argv, bprintf(&b, "GOOS_%s", goos));
|
||||
vadd(&argv, "-D");
|
||||
vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
|
||||
vadd(&argv, "-I");
|
||||
vadd(&argv, bprintf(&b, "%s", workdir));
|
||||
vadd(&argv, "-I");
|
||||
vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
|
||||
vadd(&argv, "-q");
|
||||
vadd(&argv, "-n");
|
||||
vadd(&argv, "-o");
|
||||
vadd(&argv, bpathf(&b, "%s/runtimedefs", workdir));
|
||||
vadd(&argv, "");
|
||||
p = argv.p[argv.len-1];
|
||||
for(i=0; i<nelem(runtimedefs); i++) {
|
||||
argv.p[argv.len-1] = runtimedefs[i];
|
||||
runv(nil, dir, CheckExit, &argv);
|
||||
readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir));
|
||||
bwriteb(&in, &b);
|
||||
}
|
||||
argv.p[argv.len-1] = p;
|
||||
|
||||
// Process the aggregate output.
|
||||
skip = 0;
|
||||
splitlines(&lines, bstr(&in));
|
||||
for(i=0; i<lines.len; i++) {
|
||||
p = lines.p[i];
|
||||
// Drop comment and func lines.
|
||||
if(hasprefix(p, "//") || hasprefix(p, "func"))
|
||||
continue;
|
||||
|
||||
// Note beginning of type or var decl, which can be multiline.
|
||||
// Remove duplicates. The linear check of seen here makes the
|
||||
// whole processing quadratic in aggregate, but there are only
|
||||
// about 100 declarations, so this is okay (and simple).
|
||||
if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) {
|
||||
splitfields(&fields, p);
|
||||
if(fields.len < 2)
|
||||
continue;
|
||||
if(find(fields.p[1], seen.p, seen.len) >= 0) {
|
||||
if(streq(fields.p[fields.len-1], "{"))
|
||||
skip = 1; // skip until }
|
||||
continue;
|
||||
}
|
||||
vadd(&seen, fields.p[1]);
|
||||
}
|
||||
|
||||
// Const lines are printed in original case (usually upper). Add a leading _ as needed.
|
||||
if(hasprefix(p, "const ")) {
|
||||
if('A' <= p[6] && p[6] <= 'Z')
|
||||
bwritestr(&out, "const _");
|
||||
else
|
||||
bwritestr(&out, "const ");
|
||||
bwritestr(&out, p+6);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(skip) {
|
||||
if(hasprefix(p, "}"))
|
||||
skip = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
bwritestr(&out, p);
|
||||
}
|
||||
|
||||
// Some windows specific const.
|
||||
if(streq(goos, "windows")) {
|
||||
bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB));
|
||||
}
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&in);
|
||||
bfree(&b);
|
||||
bfree(&b1);
|
||||
bfree(&out);
|
||||
vfree(&argv);
|
||||
vfree(&lines);
|
||||
vfree(&fields);
|
||||
vfree(&seen);
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "go.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
static NodeList *asmlist;
|
||||
|
||||
static void dumpexporttype(Type *t);
|
||||
|
||||
// Mark n's symbol as exported
|
||||
@ -68,6 +70,11 @@ autoexport(Node *n, int ctxt)
|
||||
// -A is for cmd/gc/mkbuiltin script, so export everything
|
||||
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
|
||||
exportsym(n);
|
||||
if(asmhdr && n->sym->pkg == localpkg && !(n->sym->flags & SymAsm)) {
|
||||
n->sym->flags |= SymAsm;
|
||||
asmlist = list(asmlist, n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -519,3 +526,37 @@ importtype(Type *pt, Type *t)
|
||||
if(debug['E'])
|
||||
print("import type %T %lT\n", pt, t);
|
||||
}
|
||||
|
||||
void
|
||||
dumpasmhdr(void)
|
||||
{
|
||||
Biobuf *b;
|
||||
NodeList *l;
|
||||
Node *n;
|
||||
Type *t;
|
||||
|
||||
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);
|
||||
for(l=asmlist; l; l=l->next) {
|
||||
n = l->n;
|
||||
if(isblanksym(n->sym))
|
||||
continue;
|
||||
switch(n->op) {
|
||||
case OLITERAL:
|
||||
Bprint(b, "#define const_%s %#V\n", n->sym->name, &n->val);
|
||||
break;
|
||||
case OTYPE:
|
||||
t = n->type;
|
||||
if(t->etype != TSTRUCT || t->map != T || t->funarg)
|
||||
break;
|
||||
for(t=t->type; t != T; t=t->down)
|
||||
if(!isblanksym(t->sym))
|
||||
Bprint(b, "#define %s_%s %d\n", n->sym->name, t->sym->name, (int)t->width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Bterm(b);
|
||||
}
|
||||
|
@ -382,6 +382,7 @@ enum
|
||||
SymExported = 1<<2, // already written out by export
|
||||
SymUniq = 1<<3,
|
||||
SymSiggen = 1<<4,
|
||||
SymAsm = 1<<5,
|
||||
};
|
||||
|
||||
struct Sym
|
||||
@ -393,6 +394,7 @@ struct Sym
|
||||
int32 npkg; // number of imported packages with this name
|
||||
uint32 uniqgen;
|
||||
Pkg* importdef; // where imported definition was found
|
||||
char* linkname; // link name
|
||||
|
||||
// saved and restored by dcopy
|
||||
Pkg* pkg;
|
||||
@ -860,6 +862,8 @@ EXTERN int32 lexlineno;
|
||||
EXTERN int32 lineno;
|
||||
EXTERN int32 prevlineno;
|
||||
|
||||
EXTERN Fmt pragcgobuf;
|
||||
|
||||
EXTERN char* infile;
|
||||
EXTERN char* outfile;
|
||||
EXTERN Biobuf* bout;
|
||||
@ -890,6 +894,7 @@ EXTERN Pkg* typelinkpkg; // fake package for runtime type info (data)
|
||||
EXTERN Pkg* weaktypepkg; // weak references to runtime type info
|
||||
EXTERN Pkg* unsafepkg; // package unsafe
|
||||
EXTERN Pkg* trackpkg; // fake package for field tracking
|
||||
EXTERN Pkg* rawpkg; // fake package for raw symbol names
|
||||
EXTERN Pkg* phash[128];
|
||||
EXTERN int tptr; // either TPTR32 or TPTR64
|
||||
extern char* runtimeimport;
|
||||
@ -897,6 +902,7 @@ extern char* unsafeimport;
|
||||
EXTERN char* myimportpath;
|
||||
EXTERN Idir* idirs;
|
||||
EXTERN char* localimport;
|
||||
EXTERN char* asmhdr;
|
||||
|
||||
EXTERN Type* types[NTYPE];
|
||||
EXTERN Type* idealstring;
|
||||
@ -1147,6 +1153,7 @@ void escapes(NodeList*);
|
||||
*/
|
||||
void autoexport(Node *n, int ctxt);
|
||||
void dumpexport(void);
|
||||
void dumpasmhdr(void);
|
||||
int exportname(char *s);
|
||||
void exportsym(Node *n);
|
||||
void importconst(Sym *s, Type *t, Node *n);
|
||||
|
200
src/cmd/gc/lex.c
200
src/cmd/gc/lex.c
@ -17,6 +17,8 @@ extern int yychar;
|
||||
int yyprev;
|
||||
int yylast;
|
||||
|
||||
static int imported_unsafe;
|
||||
|
||||
static void lexinit(void);
|
||||
static void lexinit1(void);
|
||||
static void lexfini(void);
|
||||
@ -271,6 +273,9 @@ main(int argc, char *argv[])
|
||||
flag_largemodel = 1;
|
||||
|
||||
setexp();
|
||||
|
||||
fmtstrinit(&pragcgobuf);
|
||||
quotefmtinstall();
|
||||
|
||||
outfile = nil;
|
||||
flagcount("+", "compiling runtime", &compiling_runtime);
|
||||
@ -289,6 +294,7 @@ main(int argc, char *argv[])
|
||||
flagcount("S", "print assembly listing", &debug['S']);
|
||||
flagfn0("V", "print compiler version", doversion);
|
||||
flagcount("W", "debug parse tree after type checking", &debug['W']);
|
||||
flagstr("asmhdr", "file: write assembly header to named file", &asmhdr);
|
||||
flagcount("complete", "compiling complete package (no C or assembly)", &pure_go);
|
||||
flagstr("d", "list: print debug information about items in list", &debugstr);
|
||||
flagcount("e", "no limit on number of errors reported", &debug['e']);
|
||||
@ -403,6 +409,8 @@ main(int argc, char *argv[])
|
||||
|
||||
block = 1;
|
||||
iota = -1000000;
|
||||
|
||||
imported_unsafe = 0;
|
||||
|
||||
yyparse();
|
||||
if(nsyntaxerrors != 0)
|
||||
@ -509,6 +517,9 @@ main(int argc, char *argv[])
|
||||
errorexit();
|
||||
|
||||
dumpobj();
|
||||
|
||||
if(asmhdr)
|
||||
dumpasmhdr();
|
||||
|
||||
if(nerrors+nsavederrors)
|
||||
errorexit();
|
||||
@ -724,6 +735,7 @@ importfile(Val *f, int line)
|
||||
}
|
||||
importpkg = mkpkg(f->u.sval);
|
||||
cannedimports("unsafe.6", unsafeimport);
|
||||
imported_unsafe = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1501,6 +1513,20 @@ caseout:
|
||||
return LLITERAL;
|
||||
}
|
||||
|
||||
static void pragcgo(char*);
|
||||
|
||||
static int
|
||||
more(char **pp)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = *pp;
|
||||
while(yy_isspace(*p))
|
||||
p++;
|
||||
*pp = p;
|
||||
return *p != '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* read and interpret syntax that looks like
|
||||
* //line parse.y:15
|
||||
@ -1583,9 +1609,39 @@ go:
|
||||
*cp++ = c;
|
||||
}
|
||||
*cp = 0;
|
||||
|
||||
if(strncmp(lexbuf, "go:cgo_", 7) == 0)
|
||||
pragcgo(lexbuf);
|
||||
|
||||
ep = strchr(lexbuf, ' ');
|
||||
if(ep != nil)
|
||||
*ep = 0;
|
||||
|
||||
if(strcmp(lexbuf, "go:linkname") == 0) {
|
||||
if(!imported_unsafe)
|
||||
yyerror("//go:linkname only allowed in Go files that import \"unsafe\"");
|
||||
if(ep == nil) {
|
||||
yyerror("usage: //go:linkname localname linkname");
|
||||
goto out;
|
||||
}
|
||||
cp = ep+1;
|
||||
while(yy_isspace(*cp))
|
||||
cp++;
|
||||
ep = strchr(cp, ' ');
|
||||
if(ep == nil) {
|
||||
yyerror("usage: //go:linkname localname linkname");
|
||||
goto out;
|
||||
}
|
||||
*ep++ = 0;
|
||||
while(yy_isspace(*ep))
|
||||
ep++;
|
||||
if(*ep == 0) {
|
||||
yyerror("usage: //go:linkname localname linkname");
|
||||
goto out;
|
||||
}
|
||||
lookup(cp)->linkname = strdup(ep);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(lexbuf, "go:nointerface") == 0 && fieldtrack_enabled) {
|
||||
nointerface = 1;
|
||||
@ -1604,6 +1660,150 @@ out:
|
||||
return c;
|
||||
}
|
||||
|
||||
static char*
|
||||
getimpsym(char **pp)
|
||||
{
|
||||
char *p, *start;
|
||||
|
||||
more(pp); // skip spaces
|
||||
|
||||
p = *pp;
|
||||
if(*p == '\0' || *p == '"')
|
||||
return nil;
|
||||
|
||||
start = p;
|
||||
while(*p != '\0' && !yy_isspace(*p) && *p != '"')
|
||||
p++;
|
||||
if(*p != '\0')
|
||||
*p++ = '\0';
|
||||
|
||||
*pp = p;
|
||||
return start;
|
||||
}
|
||||
|
||||
static char*
|
||||
getquoted(char **pp)
|
||||
{
|
||||
char *p, *start;
|
||||
|
||||
more(pp); // skip spaces
|
||||
|
||||
p = *pp;
|
||||
if(*p != '"')
|
||||
return nil;
|
||||
p++;
|
||||
|
||||
start = p;
|
||||
while(*p != '"') {
|
||||
if(*p == '\0')
|
||||
return nil;
|
||||
p++;
|
||||
}
|
||||
*p++ = '\0';
|
||||
*pp = p;
|
||||
return start;
|
||||
}
|
||||
|
||||
// Copied nearly verbatim from the C compiler's #pragma parser.
|
||||
// TODO: Rewrite more cleanly once the compiler is written in Go.
|
||||
static void
|
||||
pragcgo(char *text)
|
||||
{
|
||||
char *local, *remote, *p, *q, *verb;
|
||||
|
||||
for(q=text; *q != '\0' && *q != ' '; q++)
|
||||
;
|
||||
if(*q == ' ')
|
||||
*q++ = '\0';
|
||||
|
||||
verb = text+3; // skip "go:"
|
||||
|
||||
if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
|
||||
p = getquoted(&q);
|
||||
if(p == nil)
|
||||
goto err1;
|
||||
fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
|
||||
goto out;
|
||||
|
||||
err1:
|
||||
yyerror("usage: //go:cgo_dynamic_linker \"path\"");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "dynexport") == 0)
|
||||
verb = "cgo_export_dynamic";
|
||||
if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
|
||||
local = getimpsym(&q);
|
||||
if(local == nil)
|
||||
goto err2;
|
||||
if(!more(&q)) {
|
||||
fmtprint(&pragcgobuf, "%s %q\n", verb, local);
|
||||
goto out;
|
||||
}
|
||||
remote = getimpsym(&q);
|
||||
if(remote == nil)
|
||||
goto err2;
|
||||
fmtprint(&pragcgobuf, "%s %q %q\n", verb, local, remote);
|
||||
goto out;
|
||||
|
||||
err2:
|
||||
yyerror("usage: //go:%s local [remote]", verb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
|
||||
local = getimpsym(&q);
|
||||
if(local == nil)
|
||||
goto err3;
|
||||
if(!more(&q)) {
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local);
|
||||
goto out;
|
||||
}
|
||||
remote = getimpsym(&q);
|
||||
if(remote == nil)
|
||||
goto err3;
|
||||
if(!more(&q)) {
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local, remote);
|
||||
goto out;
|
||||
}
|
||||
p = getquoted(&q);
|
||||
if(p == nil)
|
||||
goto err3;
|
||||
fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local, remote, p);
|
||||
goto out;
|
||||
|
||||
err3:
|
||||
yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_import_static") == 0) {
|
||||
local = getimpsym(&q);
|
||||
if(local == nil || more(&q))
|
||||
goto err4;
|
||||
fmtprint(&pragcgobuf, "cgo_import_static %q\n", local);
|
||||
goto out;
|
||||
|
||||
err4:
|
||||
yyerror("usage: //go:cgo_import_static local");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(strcmp(verb, "cgo_ldflag") == 0) {
|
||||
p = getquoted(&q);
|
||||
if(p == nil)
|
||||
goto err5;
|
||||
fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
|
||||
goto out;
|
||||
|
||||
err5:
|
||||
yyerror("usage: //go:cgo_ldflag \"arg\"");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:;
|
||||
}
|
||||
|
||||
int32
|
||||
yylex(void)
|
||||
{
|
||||
|
@ -67,6 +67,16 @@ dumpobj(void)
|
||||
startobj = Boffset(bout);
|
||||
Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
|
||||
}
|
||||
|
||||
if(pragcgobuf.to > pragcgobuf.start) {
|
||||
if(writearchive) {
|
||||
// write empty export section; must be before cgo section
|
||||
Bprint(bout, "\n$$\n\n$$\n\n");
|
||||
}
|
||||
Bprint(bout, "\n$$ // cgo\n");
|
||||
Bprint(bout, "%s\n$$\n\n", fmtstrflush(&pragcgobuf));
|
||||
}
|
||||
|
||||
|
||||
Bprint(bout, "\n!\n");
|
||||
|
||||
@ -153,6 +163,8 @@ linksym(Sym *s)
|
||||
return s->lsym;
|
||||
if(isblanksym(s))
|
||||
s->lsym = linklookup(ctxt, "_", 0);
|
||||
else if(s->linkname != nil)
|
||||
s->lsym = linklookup(ctxt, s->linkname, 0);
|
||||
else {
|
||||
p = smprint("%s.%s", s->pkg->prefix, s->name);
|
||||
s->lsym = linklookup(ctxt, p, 0);
|
||||
|
@ -1318,7 +1318,7 @@ gengcmask(Type *t, uint8 gcmask[16])
|
||||
{
|
||||
Bvec *vec;
|
||||
vlong xoffset, nptr, i, j;
|
||||
int half, mw;
|
||||
int half;
|
||||
uint8 bits, *pos;
|
||||
|
||||
memset(gcmask, 0, 16);
|
||||
@ -1335,7 +1335,6 @@ gengcmask(Type *t, uint8 gcmask[16])
|
||||
pos = (uint8*)gcmask;
|
||||
nptr = (t->width+widthptr-1)/widthptr;
|
||||
half = 0;
|
||||
mw = 0;
|
||||
// If number of words is odd, repeat the mask.
|
||||
// This makes simpler handling of arrays in runtime.
|
||||
for(j=0; j<=(nptr%2); j++) {
|
||||
@ -1344,9 +1343,8 @@ gengcmask(Type *t, uint8 gcmask[16])
|
||||
// Some fake types (e.g. Hmap) has missing fileds.
|
||||
// twobitwalktype1 generates BitsDead for that holes,
|
||||
// replace BitsDead with BitsScalar.
|
||||
if(!mw && bits == BitsDead)
|
||||
if(bits == BitsDead)
|
||||
bits = BitsScalar;
|
||||
mw = !mw && bits == BitsMultiWord;
|
||||
bits <<= 2;
|
||||
if(half)
|
||||
bits <<= 4;
|
||||
|
@ -3802,39 +3802,25 @@ checknil(Node *x, NodeList **init)
|
||||
|
||||
/*
|
||||
* Can this type be stored directly in an interface word?
|
||||
* Yes, if the representation is a single pointer.
|
||||
*/
|
||||
int
|
||||
isdirectiface(Type *t)
|
||||
{
|
||||
// Setting IfacePointerOnly = 1 changes the
|
||||
// interface representation so that the data word
|
||||
// in an interface value must always be a pointer.
|
||||
// Setting it to 0 uses the original representation,
|
||||
// where the data word can hold a pointer or any
|
||||
// non-pointer value no bigger than a pointer.
|
||||
enum {
|
||||
IfacePointerOnly = 1,
|
||||
};
|
||||
|
||||
if(IfacePointerOnly) {
|
||||
switch(t->etype) {
|
||||
case TPTR32:
|
||||
case TPTR64:
|
||||
case TCHAN:
|
||||
case TMAP:
|
||||
case TFUNC:
|
||||
case TUNSAFEPTR:
|
||||
return 1;
|
||||
case TARRAY:
|
||||
// Array of 1 direct iface type can be direct.
|
||||
return t->bound == 1 && isdirectiface(t->type);
|
||||
case TSTRUCT:
|
||||
// Struct with 1 field of direct iface type can be direct.
|
||||
return t->type != T && t->type->down == T && isdirectiface(t->type->type);
|
||||
}
|
||||
return 0;
|
||||
switch(t->etype) {
|
||||
case TPTR32:
|
||||
case TPTR64:
|
||||
case TCHAN:
|
||||
case TMAP:
|
||||
case TFUNC:
|
||||
case TUNSAFEPTR:
|
||||
return 1;
|
||||
case TARRAY:
|
||||
// Array of 1 direct iface type can be direct.
|
||||
return t->bound == 1 && isdirectiface(t->type);
|
||||
case TSTRUCT:
|
||||
// Struct with 1 field of direct iface type can be direct.
|
||||
return t->type != T && t->type->down == T && isdirectiface(t->type->type);
|
||||
}
|
||||
|
||||
dowidth(t);
|
||||
return t->width <= widthptr;
|
||||
return 0;
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ func (b *builder) build(a *action) (err error) {
|
||||
}
|
||||
|
||||
if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
|
||||
!hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
|
||||
!hasString(a.p.SFiles, "zsys_"+buildContext.GOOS+"_"+buildContext.GOARCH+".s") {
|
||||
return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
|
||||
}
|
||||
|
||||
@ -941,7 +941,7 @@ func (b *builder) build(a *action) (err error) {
|
||||
inc := b.includeArgs("-I", a.deps)
|
||||
|
||||
// Compile Go.
|
||||
ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles)
|
||||
ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, len(sfiles) > 0, inc, gofiles)
|
||||
if len(out) > 0 {
|
||||
b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
|
||||
if err != nil {
|
||||
@ -1550,7 +1550,7 @@ type toolchain interface {
|
||||
// gc runs the compiler in a specific directory on a set of files
|
||||
// and returns the name of the generated output file.
|
||||
// The compiler runs in the directory dir.
|
||||
gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
|
||||
gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
|
||||
// cc runs the toolchain's C compiler in a directory on a C file
|
||||
// to produce an output file.
|
||||
cc(b *builder, p *Package, objdir, ofile, cfile string) error
|
||||
@ -1587,7 +1587,7 @@ func (noToolchain) linker() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
|
||||
func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
|
||||
return "", nil, noCompiler()
|
||||
}
|
||||
|
||||
@ -1623,7 +1623,7 @@ func (gcToolchain) linker() string {
|
||||
return tool(archChar + "l")
|
||||
}
|
||||
|
||||
func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
|
||||
func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
|
||||
if archive != "" {
|
||||
ofile = archive
|
||||
} else {
|
||||
@ -1660,6 +1660,9 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
|
||||
if ofile == archive {
|
||||
args = append(args, "-pack")
|
||||
}
|
||||
if asmhdr {
|
||||
args = append(args, "-asmhdr", obj+"go_asm.h")
|
||||
}
|
||||
for _, f := range gofiles {
|
||||
args = append(args, mkAbs(p.Dir, f))
|
||||
}
|
||||
@ -1824,18 +1827,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
|
||||
}
|
||||
|
||||
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
|
||||
inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
|
||||
cfile = mkAbs(p.Dir, cfile)
|
||||
warn := []string{"-w"}
|
||||
if p.usesSwig() {
|
||||
// When using SWIG, this compiler is only used to
|
||||
// compile the C files generated by SWIG.
|
||||
// We don't want warnings.
|
||||
// See issue 9065 for details.
|
||||
warn = nil
|
||||
}
|
||||
args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
|
||||
return b.run(p.Dir, p.ImportPath, nil, args)
|
||||
return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile))
|
||||
}
|
||||
|
||||
// The Gccgo toolchain.
|
||||
@ -1859,7 +1851,7 @@ func (gccgoToolchain) linker() string {
|
||||
return gccgoBin
|
||||
}
|
||||
|
||||
func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
|
||||
func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
|
||||
out := "_go_.o"
|
||||
ofile = obj + out
|
||||
gcargs := []string{"-g"}
|
||||
@ -2225,11 +2217,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
|
||||
outGo = append(outGo, gofiles...)
|
||||
|
||||
// cc _cgo_defun.c
|
||||
defunObj := obj + "_cgo_defun." + objExt
|
||||
if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
|
||||
return nil, nil, err
|
||||
_, gccgo := buildToolchain.(gccgoToolchain)
|
||||
if gccgo {
|
||||
defunObj := obj + "_cgo_defun." + objExt
|
||||
if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
outObj = append(outObj, defunObj)
|
||||
}
|
||||
outObj = append(outObj, defunObj)
|
||||
|
||||
// gcc
|
||||
var linkobj []string
|
||||
@ -2343,20 +2338,15 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
|
||||
}
|
||||
|
||||
// cgo -dynimport
|
||||
importC := obj + "_cgo_import.c"
|
||||
importGo := obj + "_cgo_import.go"
|
||||
cgoflags = []string{}
|
||||
if p.Standard && p.ImportPath == "runtime/cgo" {
|
||||
cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
|
||||
}
|
||||
if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// cc _cgo_import.ARCH
|
||||
importObj := obj + "_cgo_import." + objExt
|
||||
if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
|
||||
if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
outGo = append(outGo, importGo)
|
||||
|
||||
ofile := obj + "_all.o"
|
||||
var gccObjs, nonGccObjs []string
|
||||
@ -2390,7 +2380,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
|
||||
// NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
|
||||
// must be processed before the gcc-generated objects.
|
||||
// Put it first. http://golang.org/issue/2601
|
||||
outObj = stringList(importObj, nonGccObjs, ofile)
|
||||
outObj = stringList(nonGccObjs, ofile)
|
||||
|
||||
return outGo, outObj, nil
|
||||
}
|
||||
@ -2526,7 +2516,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
||||
|
||||
p := goFilesPackage(srcs)
|
||||
|
||||
if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil {
|
||||
if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
|
||||
return "32", nil
|
||||
}
|
||||
return "64", nil
|
||||
|
@ -1543,9 +1543,8 @@ static vlong vaddr(Link*, Addr*, Reloc*);
|
||||
static int
|
||||
isextern(LSym *s)
|
||||
{
|
||||
// All the Solaris dynamic imports from libc.so begin with "libc·", which
|
||||
// the compiler rewrites to "libc." by the time liblink gets it.
|
||||
return strncmp(s->name, "libc.", 5) == 0;
|
||||
// All the Solaris dynamic imports from libc.so begin with "libc_".
|
||||
return strncmp(s->name, "libc_", 5) == 0;
|
||||
}
|
||||
|
||||
// single-instruction no-ops of various lengths.
|
||||
|
@ -551,9 +551,10 @@ ldobjfile(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn)
|
||||
static void
|
||||
readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
|
||||
{
|
||||
int i, j, c, t, v, n, size, dupok;
|
||||
int i, j, c, t, v, n, ndata, nreloc, size, dupok;
|
||||
static int ndup;
|
||||
char *name;
|
||||
uchar *data;
|
||||
Reloc *r;
|
||||
LSym *s, *dup, *typ;
|
||||
Pcln *pc;
|
||||
@ -569,12 +570,24 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
|
||||
dupok = rdint(f);
|
||||
dupok &= 1;
|
||||
size = rdint(f);
|
||||
typ = rdsym(ctxt, f, pkg);
|
||||
rddata(f, &data, &ndata);
|
||||
nreloc = rdint(f);
|
||||
|
||||
if(v != 0)
|
||||
v = ctxt->version;
|
||||
s = linklookup(ctxt, name, v);
|
||||
dup = nil;
|
||||
if(s->type != 0 && s->type != SXREF) {
|
||||
if((t == SDATA || t == SBSS || t == SNOPTRBSS) && ndata == 0 && nreloc == 0) {
|
||||
if(s->size < size)
|
||||
s->size = size;
|
||||
if(typ != nil && s->gotype == nil)
|
||||
s->gotype = typ;
|
||||
return;
|
||||
}
|
||||
if((s->type == SDATA || s->type == SBSS || s->type == SNOPTRBSS) && s->np == 0 && s->nr == 0)
|
||||
goto overwrite;
|
||||
if(s->type != SBSS && s->type != SNOPTRBSS && !dupok && !s->dupok)
|
||||
sysfatal("duplicate symbol %s (types %d and %d) in %s and %s", s->name, s->type, t, s->file, pn);
|
||||
if(s->np > 0) {
|
||||
@ -582,28 +595,30 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
|
||||
s = linknewsym(ctxt, ".dup", ndup++); // scratch
|
||||
}
|
||||
}
|
||||
overwrite:
|
||||
s->file = pkg;
|
||||
s->dupok = dupok;
|
||||
if(t == SXREF)
|
||||
sysfatal("bad sxref");
|
||||
if(t == 0)
|
||||
sysfatal("missing type for %s in %s", name, pn);
|
||||
if(t == SBSS && (s->type == SRODATA || s->type == SNOPTRBSS))
|
||||
t = s->type;
|
||||
s->type = t;
|
||||
if(s->size < size)
|
||||
s->size = size;
|
||||
typ = rdsym(ctxt, f, pkg);
|
||||
if(typ != nil) // if bss sym defined multiple times, take type from any one def
|
||||
s->gotype = typ;
|
||||
if(dup != nil && typ != nil)
|
||||
dup->gotype = typ;
|
||||
rddata(f, &s->p, &s->np);
|
||||
s->p = data;
|
||||
s->np = ndata;
|
||||
s->maxp = s->np;
|
||||
n = rdint(f);
|
||||
if(n > 0) {
|
||||
s->r = emallocz(n * sizeof s->r[0]);
|
||||
s->nr = n;
|
||||
s->maxr = n;
|
||||
for(i=0; i<n; i++) {
|
||||
if(nreloc > 0) {
|
||||
s->r = emallocz(nreloc * sizeof s->r[0]);
|
||||
s->nr = nreloc;
|
||||
s->maxr = nreloc;
|
||||
for(i=0; i<nreloc; i++) {
|
||||
r = &s->r[i];
|
||||
r->off = rdint(f);
|
||||
r->siz = rdint(f);
|
||||
|
@ -1588,9 +1588,8 @@ func (gc *gcProg) align(a uintptr) {
|
||||
|
||||
// These constants must stay in sync with ../runtime/mgc0.h.
|
||||
const (
|
||||
bitsScalar = 1
|
||||
bitsPointer = 2
|
||||
bitsMultiWord = 3
|
||||
bitsScalar = 1
|
||||
bitsPointer = 2
|
||||
|
||||
bitsIface = 2
|
||||
bitsEface = 3
|
||||
|
@ -244,8 +244,8 @@ rm -f runtest
|
||||
[ "$GOOS" == nacl ] ||
|
||||
(
|
||||
echo
|
||||
echo '# Checking API compatibility.'
|
||||
time go run $GOROOT/src/cmd/api/run.go || exit 1
|
||||
echo '# SKIPPING API CHECK UNTIL ALL SYSTEMS BUILD.'
|
||||
# time go run $GOROOT/src/cmd/api/run.go || exit 1
|
||||
) || exit $?
|
||||
|
||||
echo
|
||||
|
@ -314,9 +314,6 @@ const hashRandomBytes = 32
|
||||
|
||||
var aeskeysched [hashRandomBytes]byte
|
||||
|
||||
//go:noescape
|
||||
func get_random_data(rnd *unsafe.Pointer, n *int32)
|
||||
|
||||
func init() {
|
||||
if theGoos == "nacl" {
|
||||
return
|
||||
|
15
src/runtime/arch1_386.go
Normal file
15
src/runtime/arch1_386.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
thechar = '8'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64
|
||||
_PhysPageSize = _NaCl*65536 + (1-_NaCl)*4096 // 4k normally; 64k on NaCl
|
||||
_PCQuantum = 1
|
||||
_Int64Align = 4
|
||||
)
|
15
src/runtime/arch1_amd64.go
Normal file
15
src/runtime/arch1_amd64.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
thechar = '6'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 64
|
||||
_RuntimeGogoBytes = 64 + (_Plan9|_Solaris|_Windows)*16
|
||||
_PhysPageSize = 4096
|
||||
_PCQuantum = 1
|
||||
_Int64Align = 8
|
||||
)
|
15
src/runtime/arch1_arm.go
Normal file
15
src/runtime/arch1_arm.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
package runtime
|
||||
|
||||
const (
|
||||
thechar = '5'
|
||||
_BigEndian = 0
|
||||
_CacheLineSize = 32
|
||||
_RuntimeGogoBytes = 60
|
||||
_PhysPageSize = 65536*_NaCl + 4096*(1-_NaCl)
|
||||
_PCQuantum = 4
|
||||
_Int64Align = 4
|
||||
)
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
enum {
|
||||
thechar = '8',
|
||||
BigEndian = 0,
|
||||
CacheLineSize = 64,
|
||||
RuntimeGogoBytes = 64,
|
||||
#ifdef GOOS_nacl
|
||||
PhysPageSize = 65536,
|
||||
#else
|
||||
PhysPageSize = 4096,
|
||||
#endif
|
||||
PCQuantum = 1,
|
||||
Int64Align = 4
|
||||
};
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
enum {
|
||||
thechar = '6',
|
||||
BigEndian = 0,
|
||||
CacheLineSize = 64,
|
||||
#ifdef GOOS_solaris
|
||||
RuntimeGogoBytes = 80,
|
||||
#else
|
||||
#ifdef GOOS_windows
|
||||
RuntimeGogoBytes = 80,
|
||||
#else
|
||||
#ifdef GOOS_plan9
|
||||
RuntimeGogoBytes = 80,
|
||||
#else
|
||||
RuntimeGogoBytes = 64,
|
||||
#endif // Plan 9
|
||||
#endif // Windows
|
||||
#endif // Solaris
|
||||
PhysPageSize = 4096,
|
||||
PCQuantum = 1,
|
||||
Int64Align = 8
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
enum {
|
||||
thechar = '5',
|
||||
BigEndian = 0,
|
||||
CacheLineSize = 32,
|
||||
RuntimeGogoBytes = 60,
|
||||
#ifdef GOOS_nacl
|
||||
PhysPageSize = 65536,
|
||||
#else
|
||||
PhysPageSize = 4096,
|
||||
#endif
|
||||
PCQuantum = 4,
|
||||
Int64Align = 4
|
||||
};
|
@ -12,3 +12,8 @@ DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2
|
||||
DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0
|
||||
GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8
|
||||
|
||||
TEXT runtime·nop(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
GLOBL runtime·mheap_(SB), NOPTR, $0
|
||||
GLOBL runtime·memstats(SB), NOPTR, $0
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "zasm_GOOS_GOARCH.h"
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
@ -49,7 +50,7 @@ nocpuinfo:
|
||||
// update stackguard after _cgo_init
|
||||
MOVL $runtime·g0(SB), CX
|
||||
MOVL (g_stack+stack_lo)(CX), AX
|
||||
ADDL $const_StackGuard, AX
|
||||
ADDL $const__StackGuard, AX
|
||||
MOVL AX, g_stackguard0(CX)
|
||||
MOVL AX, g_stackguard1(CX)
|
||||
|
||||
@ -199,62 +200,49 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
|
||||
JMP AX
|
||||
RET
|
||||
|
||||
// switchtoM is a dummy routine that onM leaves at the bottom
|
||||
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
|
||||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the M stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the system stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
|
||||
RET
|
||||
|
||||
// func onM_signalok(fn func())
|
||||
TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
|
||||
// func systemstack(fn func())
|
||||
TEXT runtime·systemstack(SB), NOSPLIT, $0-4
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX // AX = g
|
||||
MOVL g_m(AX), BX // BX = m
|
||||
|
||||
MOVL m_gsignal(BX), DX // DX = gsignal
|
||||
CMPL AX, DX
|
||||
JEQ ongsignal
|
||||
JMP runtime·onM(SB)
|
||||
|
||||
ongsignal:
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
MOVL DI, DX
|
||||
MOVL 0(DI), DI
|
||||
CALL DI
|
||||
RET
|
||||
|
||||
// func onM(fn func())
|
||||
TEXT runtime·onM(SB), NOSPLIT, $0-4
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX // AX = g
|
||||
MOVL g_m(AX), BX // BX = m
|
||||
JEQ noswitch
|
||||
|
||||
MOVL m_g0(BX), DX // DX = g0
|
||||
CMPL AX, DX
|
||||
JEQ onm
|
||||
JEQ noswitch
|
||||
|
||||
MOVL m_curg(BX), BP
|
||||
CMPL AX, BP
|
||||
JEQ oncurg
|
||||
JEQ switch
|
||||
|
||||
// Not g0, not curg. Must be gsignal, but that's not allowed.
|
||||
// Bad: g is not gsignal, not g0, not curg. What is it?
|
||||
// Hide call from linker nosplit analysis.
|
||||
MOVL $runtime·badonm(SB), AX
|
||||
MOVL $runtime·badsystemstack(SB), AX
|
||||
CALL AX
|
||||
|
||||
oncurg:
|
||||
switch:
|
||||
// save our state in g->sched. Pretend to
|
||||
// be switchtoM if the G stack is scanned.
|
||||
MOVL $runtime·switchtoM(SB), (g_sched+gobuf_pc)(AX)
|
||||
// be systemstack_switch if the G stack is scanned.
|
||||
MOVL $runtime·systemstack_switch(SB), (g_sched+gobuf_pc)(AX)
|
||||
MOVL SP, (g_sched+gobuf_sp)(AX)
|
||||
MOVL AX, (g_sched+gobuf_g)(AX)
|
||||
|
||||
// switch to g0
|
||||
MOVL DX, g(CX)
|
||||
MOVL (g_sched+gobuf_sp)(DX), BX
|
||||
// make it look like mstart called onM on g0, to stop traceback
|
||||
// make it look like mstart called systemstack on g0, to stop traceback
|
||||
SUBL $4, BX
|
||||
MOVL $runtime·mstart(SB), DX
|
||||
MOVL DX, 0(BX)
|
||||
@ -275,8 +263,8 @@ oncurg:
|
||||
MOVL $0, (g_sched+gobuf_sp)(AX)
|
||||
RET
|
||||
|
||||
onm:
|
||||
// already on m stack, just call directly
|
||||
noswitch:
|
||||
// already on system stack, just call directly
|
||||
MOVL DI, DX
|
||||
MOVL 0(DI), DI
|
||||
CALL DI
|
||||
@ -740,7 +728,7 @@ needm:
|
||||
// the same SP back to m->sched.sp. That seems redundant,
|
||||
// but if an unrecovered panic happens, unwindm will
|
||||
// restore the g->sched.sp from the stack location
|
||||
// and then onM will try to use it. If we don't set it here,
|
||||
// and then systemstack will try to use it. If we don't set it here,
|
||||
// that restored SP will be uninitialized (typically 0) and
|
||||
// will not be usable.
|
||||
MOVL m_g0(BP), SI
|
||||
@ -2290,3 +2278,10 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
|
||||
TEXT runtime·goexit(SB),NOSPLIT,$0-0
|
||||
BYTE $0x90 // NOP
|
||||
CALL runtime·goexit1(SB) // does not return
|
||||
|
||||
TEXT runtime·getg(SB),NOSPLIT,$0-4
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX
|
||||
MOVL AX, ret+0(FP)
|
||||
RET
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "zasm_GOOS_GOARCH.h"
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
@ -47,7 +48,7 @@ nocpuinfo:
|
||||
// update stackguard after _cgo_init
|
||||
MOVQ $runtime·g0(SB), CX
|
||||
MOVQ (g_stack+stack_lo)(CX), AX
|
||||
ADDQ $const_StackGuard, AX
|
||||
ADDQ $const__StackGuard, AX
|
||||
MOVQ AX, g_stackguard0(CX)
|
||||
MOVQ AX, g_stackguard1(CX)
|
||||
|
||||
@ -189,55 +190,41 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-8
|
||||
JMP AX
|
||||
RET
|
||||
|
||||
// switchtoM is a dummy routine that onM leaves at the bottom
|
||||
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
|
||||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the M stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the system stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
|
||||
RET
|
||||
|
||||
// func onM_signalok(fn func())
|
||||
TEXT runtime·onM_signalok(SB), NOSPLIT, $0-8
|
||||
// func systemstack(fn func())
|
||||
TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
||||
MOVQ fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), AX // AX = g
|
||||
MOVQ g_m(AX), BX // BX = m
|
||||
|
||||
MOVQ m_gsignal(BX), DX // DX = gsignal
|
||||
CMPQ AX, DX
|
||||
JEQ ongsignal
|
||||
JMP runtime·onM(SB)
|
||||
|
||||
ongsignal:
|
||||
MOVQ fn+0(FP), DI // DI = fn
|
||||
MOVQ DI, DX
|
||||
MOVQ 0(DI), DI
|
||||
CALL DI
|
||||
RET
|
||||
|
||||
// func onM(fn func())
|
||||
TEXT runtime·onM(SB), NOSPLIT, $0-8
|
||||
MOVQ fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), AX // AX = g
|
||||
MOVQ g_m(AX), BX // BX = m
|
||||
JEQ noswitch
|
||||
|
||||
MOVQ m_g0(BX), DX // DX = g0
|
||||
CMPQ AX, DX
|
||||
JEQ onm
|
||||
JEQ noswitch
|
||||
|
||||
MOVQ m_curg(BX), BP
|
||||
CMPQ AX, BP
|
||||
JEQ oncurg
|
||||
JEQ switch
|
||||
|
||||
// Not g0, not curg. Must be gsignal, but that's not allowed.
|
||||
// Hide call from linker nosplit analysis.
|
||||
MOVQ $runtime·badonm(SB), AX
|
||||
// Bad: g is not gsignal, not g0, not curg. What is it?
|
||||
MOVQ $runtime·badsystemstack(SB), AX
|
||||
CALL AX
|
||||
|
||||
oncurg:
|
||||
switch:
|
||||
// save our state in g->sched. Pretend to
|
||||
// be switchtoM if the G stack is scanned.
|
||||
MOVQ $runtime·switchtoM(SB), BP
|
||||
// be systemstack_switch if the G stack is scanned.
|
||||
MOVQ $runtime·systemstack_switch(SB), BP
|
||||
MOVQ BP, (g_sched+gobuf_pc)(AX)
|
||||
MOVQ SP, (g_sched+gobuf_sp)(AX)
|
||||
MOVQ AX, (g_sched+gobuf_g)(AX)
|
||||
@ -245,7 +232,7 @@ oncurg:
|
||||
// switch to g0
|
||||
MOVQ DX, g(CX)
|
||||
MOVQ (g_sched+gobuf_sp)(DX), BX
|
||||
// make it look like mstart called onM on g0, to stop traceback
|
||||
// make it look like mstart called systemstack on g0, to stop traceback
|
||||
SUBQ $8, BX
|
||||
MOVQ $runtime·mstart(SB), DX
|
||||
MOVQ DX, 0(BX)
|
||||
@ -266,7 +253,7 @@ oncurg:
|
||||
MOVQ $0, (g_sched+gobuf_sp)(AX)
|
||||
RET
|
||||
|
||||
onm:
|
||||
noswitch:
|
||||
// already on m stack, just call directly
|
||||
MOVQ DI, DX
|
||||
MOVQ 0(DI), DI
|
||||
@ -726,7 +713,7 @@ needm:
|
||||
// the same SP back to m->sched.sp. That seems redundant,
|
||||
// but if an unrecovered panic happens, unwindm will
|
||||
// restore the g->sched.sp from the stack location
|
||||
// and then onM will try to use it. If we don't set it here,
|
||||
// and then systemstack will try to use it. If we don't set it here,
|
||||
// that restored SP will be uninitialized (typically 0) and
|
||||
// will not be usable.
|
||||
MOVQ m_g0(BP), SI
|
||||
@ -2235,3 +2222,9 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0
|
||||
TEXT runtime·goexit(SB),NOSPLIT,$0-0
|
||||
BYTE $0x90 // NOP
|
||||
CALL runtime·goexit1(SB) // does not return
|
||||
|
||||
TEXT runtime·getg(SB),NOSPLIT,$0-8
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), AX
|
||||
MOVQ AX, ret+0(FP)
|
||||
RET
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "zasm_GOOS_GOARCH.h"
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
@ -164,55 +165,42 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
|
||||
JMP AX
|
||||
RET
|
||||
|
||||
// switchtoM is a dummy routine that onM leaves at the bottom
|
||||
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
|
||||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the M stack because the one at the top of
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
|
||||
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
|
||||
RET
|
||||
|
||||
// func onM_signalok(fn func())
|
||||
TEXT runtime·onM_signalok(SB), NOSPLIT, $0-4
|
||||
// func systemstack(fn func())
|
||||
TEXT runtime·systemstack(SB), NOSPLIT, $0-4
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX // AX = g
|
||||
MOVL g_m(AX), BX // BX = m
|
||||
|
||||
MOVL m_gsignal(BX), DX // DX = gsignal
|
||||
CMPL AX, DX
|
||||
JEQ ongsignal
|
||||
JMP runtime·onM(SB)
|
||||
|
||||
ongsignal:
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
MOVL DI, DX
|
||||
MOVL 0(DI), DI
|
||||
CALL DI
|
||||
RET
|
||||
|
||||
// func onM(fn func())
|
||||
TEXT runtime·onM(SB), NOSPLIT, $0-4
|
||||
MOVL fn+0(FP), DI // DI = fn
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX // AX = g
|
||||
MOVL g_m(AX), BX // BX = m
|
||||
JEQ noswitch
|
||||
|
||||
MOVL m_g0(BX), DX // DX = g0
|
||||
CMPL AX, DX
|
||||
JEQ onm
|
||||
JEQ noswitch
|
||||
|
||||
MOVL m_curg(BX), R8
|
||||
CMPL AX, R8
|
||||
JEQ oncurg
|
||||
JEQ switch
|
||||
|
||||
// Not g0, not curg. Must be gsignal, but that's not allowed.
|
||||
// Hide call from linker nosplit analysis.
|
||||
MOVL $runtime·badonm(SB), AX
|
||||
MOVL $runtime·badsystemstack(SB), AX
|
||||
CALL AX
|
||||
|
||||
oncurg:
|
||||
switch:
|
||||
// save our state in g->sched. Pretend to
|
||||
// be switchtoM if the G stack is scanned.
|
||||
MOVL $runtime·switchtoM(SB), SI
|
||||
// be systemstack_switch if the G stack is scanned.
|
||||
MOVL $runtime·systemstack_switch(SB), SI
|
||||
MOVL SI, (g_sched+gobuf_pc)(AX)
|
||||
MOVL SP, (g_sched+gobuf_sp)(AX)
|
||||
MOVL AX, (g_sched+gobuf_g)(AX)
|
||||
@ -236,7 +224,7 @@ oncurg:
|
||||
MOVL $0, (g_sched+gobuf_sp)(AX)
|
||||
RET
|
||||
|
||||
onm:
|
||||
noswitch:
|
||||
// already on m stack, just call directly
|
||||
MOVL DI, DX
|
||||
MOVL 0(DI), DI
|
||||
@ -1085,3 +1073,9 @@ TEXT runtime·return0(SB), NOSPLIT, $0
|
||||
TEXT runtime·goexit(SB),NOSPLIT,$0-0
|
||||
BYTE $0x90 // NOP
|
||||
CALL runtime·goexit1(SB) // does not return
|
||||
|
||||
TEXT runtime·getg(SB),NOSPLIT,$0-4
|
||||
get_tls(CX)
|
||||
MOVL g(CX), AX
|
||||
MOVL AX, ret+0(FP)
|
||||
RET
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "zasm_GOOS_GOARCH.h"
|
||||
#include "go_asm.h"
|
||||
#include "go_tls.h"
|
||||
#include "funcdata.h"
|
||||
#include "textflag.h"
|
||||
|
||||
@ -54,7 +55,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$-4
|
||||
nocgo:
|
||||
// update stackguard after _cgo_init
|
||||
MOVW (g_stack+stack_lo)(g), R0
|
||||
ADD $const_StackGuard, R0
|
||||
ADD $const__StackGuard, R0
|
||||
MOVW R0, g_stackguard0(g)
|
||||
MOVW R0, g_stackguard1(g)
|
||||
|
||||
@ -190,53 +191,42 @@ TEXT runtime·mcall(SB),NOSPLIT,$-4-4
|
||||
B runtime·badmcall2(SB)
|
||||
RET
|
||||
|
||||
// switchtoM is a dummy routine that onM leaves at the bottom
|
||||
// systemstack_switch is a dummy routine that systemstack leaves at the bottom
|
||||
// of the G stack. We need to distinguish the routine that
|
||||
// lives at the bottom of the G stack from the one that lives
|
||||
// at the top of the M stack because the one at the top of
|
||||
// the M stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·switchtoM(SB),NOSPLIT,$0-0
|
||||
// at the top of the system stack because the one at the top of
|
||||
// the system stack terminates the stack walk (see topofstack()).
|
||||
TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
|
||||
MOVW $0, R0
|
||||
BL (R0) // clobber lr to ensure push {lr} is kept
|
||||
RET
|
||||
|
||||
// func onM_signalok(fn func())
|
||||
TEXT runtime·onM_signalok(SB), NOSPLIT, $-4-4
|
||||
MOVW g_m(g), R1
|
||||
MOVW m_gsignal(R1), R2
|
||||
CMP g, R2
|
||||
B.EQ ongsignal
|
||||
B runtime·onM(SB)
|
||||
|
||||
ongsignal:
|
||||
MOVW fn+0(FP), R0
|
||||
MOVW R0, R7
|
||||
MOVW 0(R0), R0
|
||||
BL (R0)
|
||||
RET
|
||||
|
||||
// func onM(fn func())
|
||||
TEXT runtime·onM(SB),NOSPLIT,$0-4
|
||||
// func systemstack(fn func())
|
||||
TEXT runtime·systemstack(SB),NOSPLIT,$0-4
|
||||
MOVW fn+0(FP), R0 // R0 = fn
|
||||
MOVW g_m(g), R1 // R1 = m
|
||||
|
||||
MOVW m_gsignal(R1), R2 // R2 = gsignal
|
||||
CMP g, R2
|
||||
B.EQ noswitch
|
||||
|
||||
MOVW m_g0(R1), R2 // R2 = g0
|
||||
CMP g, R2
|
||||
B.EQ onm
|
||||
B.EQ noswitch
|
||||
|
||||
MOVW m_curg(R1), R3
|
||||
CMP g, R3
|
||||
B.EQ oncurg
|
||||
B.EQ switch
|
||||
|
||||
// Not g0, not curg. Must be gsignal, but that's not allowed.
|
||||
// Bad: g is not gsignal, not g0, not curg. What is it?
|
||||
// Hide call from linker nosplit analysis.
|
||||
MOVW $runtime·badonm(SB), R0
|
||||
MOVW $runtime·badsystemstack(SB), R0
|
||||
BL (R0)
|
||||
|
||||
oncurg:
|
||||
switch:
|
||||
// save our state in g->sched. Pretend to
|
||||
// be switchtoM if the G stack is scanned.
|
||||
MOVW $runtime·switchtoM(SB), R3
|
||||
// be systemstack_switch if the G stack is scanned.
|
||||
MOVW $runtime·systemstack_switch(SB), R3
|
||||
ADD $4, R3, R3 // get past push {lr}
|
||||
MOVW R3, (g_sched+gobuf_pc)(g)
|
||||
MOVW SP, (g_sched+gobuf_sp)(g)
|
||||
@ -249,7 +239,7 @@ oncurg:
|
||||
BL setg<>(SB)
|
||||
MOVW R5, R0
|
||||
MOVW (g_sched+gobuf_sp)(R2), R3
|
||||
// make it look like mstart called onM on g0, to stop traceback
|
||||
// make it look like mstart called systemstack on g0, to stop traceback
|
||||
SUB $4, R3, R3
|
||||
MOVW $runtime·mstart(SB), R4
|
||||
MOVW R4, 0(R3)
|
||||
@ -269,7 +259,7 @@ oncurg:
|
||||
MOVW R3, (g_sched+gobuf_sp)(g)
|
||||
RET
|
||||
|
||||
onm:
|
||||
noswitch:
|
||||
MOVW R0, R7
|
||||
MOVW 0(R0), R0
|
||||
BL (R0)
|
||||
@ -564,7 +554,7 @@ TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-12
|
||||
// the same SP back to m->sched.sp. That seems redundant,
|
||||
// but if an unrecovered panic happens, unwindm will
|
||||
// restore the g->sched.sp from the stack location
|
||||
// and then onM will try to use it. If we don't set it here,
|
||||
// and then systemstack will try to use it. If we don't set it here,
|
||||
// that restored SP will be uninitialized (typically 0) and
|
||||
// will not be usable.
|
||||
MOVW g_m(g), R8
|
||||
@ -1326,3 +1316,7 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$8
|
||||
TEXT runtime·goexit(SB),NOSPLIT,$-4-0
|
||||
MOVW R0, R0 // NOP
|
||||
BL runtime·goexit1(SB) // does not return
|
||||
|
||||
TEXT runtime·getg(SB),NOSPLIT,$-4-4
|
||||
MOVW g, ret+0(FP)
|
||||
RET
|
||||
|
@ -1,81 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// +build !arm
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//go:noescape
|
||||
func xadd(ptr *uint32, delta int32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xadd64(ptr *uint64, delta int64) uint64
|
||||
|
||||
//go:noescape
|
||||
func xchg(ptr *uint32, new uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xchg64(ptr *uint64, new uint64) uint64
|
||||
|
||||
// Cannot use noescape here: ptr does not but new does escape.
|
||||
// Instead use noescape(ptr) in wrapper below.
|
||||
func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:nosplit
|
||||
func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
|
||||
old := xchgp1(noescape(ptr), new)
|
||||
writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
|
||||
return old
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func xchguintptr(ptr *uintptr, new uintptr) uintptr
|
||||
|
||||
//go:noescape
|
||||
func atomicload(ptr *uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func atomicload64(ptr *uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func atomicor8(ptr *uint8, val uint8)
|
||||
|
||||
//go:noescape
|
||||
func cas64(ptr *uint64, old, new uint64) bool
|
||||
|
||||
//go:noescape
|
||||
func atomicstore(ptr *uint32, val uint32)
|
||||
|
||||
//go:noescape
|
||||
func atomicstore64(ptr *uint64, val uint64)
|
||||
|
||||
// Cannot use noescape here: ptr does not but val does escape.
|
||||
// Instead use noescape(ptr) in wrapper below.
|
||||
func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
|
||||
|
||||
//go:nosplit
|
||||
func atomicstorep(ptr unsafe.Pointer, val unsafe.Pointer) {
|
||||
atomicstorep1(noescape(ptr), val)
|
||||
// TODO(rsc): Why does the compiler think writebarrierptr_nostore's dst argument escapes?
|
||||
writebarrierptr_nostore((*uintptr)(noescape(ptr)), uintptr(val))
|
||||
}
|
||||
|
||||
// Cannot use noescape here: ptr does not but new does escape.
|
||||
// Instead use noescape(ptr) in wrapper below.
|
||||
func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
|
||||
|
||||
//go:nosplit
|
||||
func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
|
||||
ok := casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), old, new)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
|
||||
return true
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "runtime.h"
|
||||
#include "textflag.h"
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
uint32
|
||||
runtime·atomicload(uint32 volatile* addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·atomicloadp(void* volatile* addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
uint64
|
||||
runtime·xadd64(uint64 volatile* addr, int64 v)
|
||||
{
|
||||
uint64 old;
|
||||
|
||||
do
|
||||
old = *addr;
|
||||
while(!runtime·cas64(addr, old, old+v));
|
||||
|
||||
return old+v;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
uint64
|
||||
runtime·xchg64(uint64 volatile* addr, uint64 v)
|
||||
{
|
||||
uint64 old;
|
||||
|
||||
do
|
||||
old = *addr;
|
||||
while(!runtime·cas64(addr, old, v));
|
||||
|
||||
return old;
|
||||
}
|
91
src/runtime/atomic_386.go
Normal file
91
src/runtime/atomic_386.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// The calls to nop are to keep these functions from being inlined.
|
||||
// If they are inlined we have no guarantee that later rewrites of the
|
||||
// code by optimizers will preserve the relative order of memory accesses.
|
||||
|
||||
//go:nosplit
|
||||
func atomicload(ptr *uint32) uint32 {
|
||||
nop()
|
||||
return *ptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
|
||||
nop()
|
||||
return *(*unsafe.Pointer)(ptr)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func xadd64(ptr *uint64, delta int64) uint64 {
|
||||
for {
|
||||
old := *ptr
|
||||
if cas64(ptr, old, old+uint64(delta)) {
|
||||
return old + uint64(delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func xchg64(ptr *uint64, new uint64) uint64 {
|
||||
for {
|
||||
old := *ptr
|
||||
if cas64(ptr, old, new) {
|
||||
return old
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func xadd(ptr *uint32, delta int32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xchg(ptr *uint32, new uint32) uint32
|
||||
|
||||
// xchgp cannot have a go:noescape annotation, because
|
||||
// while ptr does not escape, new does. If new is marked as
|
||||
// not escaping, the compiler will make incorrect escape analysis
|
||||
// decisions about the value being xchg'ed.
|
||||
// Instead, make xchgp a wrapper around the actual atomic.
|
||||
// When calling the wrapper we mark ptr as noescape explicitly.
|
||||
|
||||
//go:nosplit
|
||||
func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
|
||||
return xchgp1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func xchguintptr(ptr *uintptr, new uintptr) uintptr
|
||||
|
||||
//go:noescape
|
||||
func atomicload64(ptr *uint64) uint64
|
||||
|
||||
//go:noescape
|
||||
func atomicor8(ptr *uint8, val uint8)
|
||||
|
||||
//go:noescape
|
||||
func cas64(ptr *uint64, old, new uint64) bool
|
||||
|
||||
//go:noescape
|
||||
func atomicstore(ptr *uint32, val uint32)
|
||||
|
||||
//go:noescape
|
||||
func atomicstore64(ptr *uint64, val uint64)
|
||||
|
||||
// atomicstorep cannot have a go:noescape annotation.
|
||||
// See comment above for xchgp.
|
||||
|
||||
//go:nosplit
|
||||
func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
|
||||
atomicstorep1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64 amd64p32
|
||||
|
||||
#include "runtime.h"
|
||||
#include "textflag.h"
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
uint32
|
||||
runtime·atomicload(uint32 volatile* addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
uint64
|
||||
runtime·atomicload64(uint64 volatile* addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·atomicloadp(void* volatile* addr)
|
||||
{
|
||||
return *addr;
|
||||
}
|
82
src/runtime/atomic_amd64x.go
Normal file
82
src/runtime/atomic_amd64x.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build amd64 amd64p32
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// The calls to nop are to keep these functions from being inlined.
|
||||
// If they are inlined we have no guarantee that later rewrites of the
|
||||
// code by optimizers will preserve the relative order of memory accesses.
|
||||
|
||||
//go:nosplit
|
||||
func atomicload(ptr *uint32) uint32 {
|
||||
nop()
|
||||
return *ptr
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
|
||||
nop()
|
||||
return *(*unsafe.Pointer)(ptr)
|
||||
}
|
||||
|
||||
//go:nosplit
|
||||
func atomicload64(ptr *uint64) uint64 {
|
||||
nop()
|
||||
return *ptr
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func xadd(ptr *uint32, delta int32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xadd64(ptr *uint64, delta int64) uint64
|
||||
|
||||
//go:noescape
|
||||
func xchg(ptr *uint32, new uint32) uint32
|
||||
|
||||
//go:noescape
|
||||
func xchg64(ptr *uint64, new uint64) uint64
|
||||
|
||||
// xchgp cannot have a go:noescape annotation, because
|
||||
// while ptr does not escape, new does. If new is marked as
|
||||
// not escaping, the compiler will make incorrect escape analysis
|
||||
// decisions about the value being xchg'ed.
|
||||
// Instead, make xchgp a wrapper around the actual atomic.
|
||||
// When calling the wrapper we mark ptr as noescape explicitly.
|
||||
|
||||
//go:nosplit
|
||||
func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
|
||||
return xchgp1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
|
||||
|
||||
//go:noescape
|
||||
func xchguintptr(ptr *uintptr, new uintptr) uintptr
|
||||
|
||||
//go:noescape
|
||||
func atomicor8(ptr *uint8, val uint8)
|
||||
|
||||
//go:noescape
|
||||
func cas64(ptr *uint64, old, new uint64) bool
|
||||
|
||||
//go:noescape
|
||||
func atomicstore(ptr *uint32, val uint32)
|
||||
|
||||
//go:noescape
|
||||
func atomicstore64(ptr *uint64, val uint64)
|
||||
|
||||
// atomicstorep cannot have a go:noescape annotation.
|
||||
// See comment above for xchgp.
|
||||
|
||||
//go:nosplit
|
||||
func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
|
||||
atomicstorep1(noescape(ptr), new)
|
||||
}
|
||||
|
||||
func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
|
@ -85,7 +85,7 @@ func atomicstore(addr *uint32, v uint32) {
|
||||
//go:nosplit
|
||||
func cas64(addr *uint64, old, new uint64) bool {
|
||||
var ok bool
|
||||
onM(func() {
|
||||
systemstack(func() {
|
||||
lock(addrLock(addr))
|
||||
if *addr == old {
|
||||
*addr = new
|
||||
@ -99,7 +99,7 @@ func cas64(addr *uint64, old, new uint64) bool {
|
||||
//go:nosplit
|
||||
func xadd64(addr *uint64, delta int64) uint64 {
|
||||
var r uint64
|
||||
onM(func() {
|
||||
systemstack(func() {
|
||||
lock(addrLock(addr))
|
||||
r = *addr + uint64(delta)
|
||||
*addr = r
|
||||
@ -111,7 +111,7 @@ func xadd64(addr *uint64, delta int64) uint64 {
|
||||
//go:nosplit
|
||||
func xchg64(addr *uint64, v uint64) uint64 {
|
||||
var r uint64
|
||||
onM(func() {
|
||||
systemstack(func() {
|
||||
lock(addrLock(addr))
|
||||
r = *addr
|
||||
*addr = v
|
||||
@ -123,7 +123,7 @@ func xchg64(addr *uint64, v uint64) uint64 {
|
||||
//go:nosplit
|
||||
func atomicload64(addr *uint64) uint64 {
|
||||
var r uint64
|
||||
onM(func() {
|
||||
systemstack(func() {
|
||||
lock(addrLock(addr))
|
||||
r = *addr
|
||||
unlock(addrLock(addr))
|
||||
@ -133,7 +133,7 @@ func atomicload64(addr *uint64) uint64 {
|
||||
|
||||
//go:nosplit
|
||||
func atomicstore64(addr *uint64, v uint64) {
|
||||
onM(func() {
|
||||
systemstack(func() {
|
||||
lock(addrLock(addr))
|
||||
*addr = v
|
||||
unlock(addrLock(addr))
|
||||
|
23
src/runtime/cgo.go
Normal file
23
src/runtime/cgo.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
//go:cgo_export_static main
|
||||
|
||||
// Filled in by runtime/cgo when linked into binary.
|
||||
|
||||
//go:linkname _cgo_init _cgo_init
|
||||
//go:linkname _cgo_malloc _cgo_malloc
|
||||
//go:linkname _cgo_free _cgo_free
|
||||
//go:linkname _cgo_thread_start _cgo_thread_start
|
||||
|
||||
var (
|
||||
_cgo_init unsafe.Pointer
|
||||
_cgo_malloc unsafe.Pointer
|
||||
_cgo_free unsafe.Pointer
|
||||
_cgo_thread_start unsafe.Pointer
|
||||
)
|
@ -1,83 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include "../runtime.h"
|
||||
#include "../cgocall.h"
|
||||
#include "textflag.h"
|
||||
|
||||
// These utility functions are available to be called from code
|
||||
// compiled with gcc via crosscall2.
|
||||
|
||||
// The declaration of crosscall2 is:
|
||||
// void crosscall2(void (*fn)(void *, int), void *, int);
|
||||
//
|
||||
// We need to export the symbol crosscall2 in order to support
|
||||
// callbacks from shared libraries. This applies regardless of
|
||||
// linking mode.
|
||||
#pragma cgo_export_static crosscall2
|
||||
#pragma cgo_export_dynamic crosscall2
|
||||
|
||||
// Allocate memory. This allocates the requested number of bytes in
|
||||
// memory controlled by the Go runtime. The allocated memory will be
|
||||
// zeroed. You are responsible for ensuring that the Go garbage
|
||||
// collector can see a pointer to the allocated memory for as long as
|
||||
// it is valid, e.g., by storing a pointer in a local variable in your
|
||||
// C function, or in memory allocated by the Go runtime. If the only
|
||||
// pointers are in a C global variable or in memory allocated via
|
||||
// malloc, then the Go garbage collector may collect the memory.
|
||||
|
||||
// Call like this in code compiled with gcc:
|
||||
// struct { size_t len; void *ret; } a;
|
||||
// a.len = /* number of bytes to allocate */;
|
||||
// crosscall2(_cgo_allocate, &a, sizeof a);
|
||||
// /* Here a.ret is a pointer to the allocated memory. */
|
||||
|
||||
void runtime·_cgo_allocate_internal(void);
|
||||
|
||||
#pragma cgo_export_static _cgo_allocate
|
||||
#pragma cgo_export_dynamic _cgo_allocate
|
||||
#pragma textflag NOSPLIT
|
||||
void
|
||||
_cgo_allocate(void *a, int32 n)
|
||||
{
|
||||
runtime·cgocallback((void(*)(void))runtime·_cgo_allocate_internal, a, n);
|
||||
}
|
||||
|
||||
// Panic. The argument is converted into a Go string.
|
||||
|
||||
// Call like this in code compiled with gcc:
|
||||
// struct { const char *p; } a;
|
||||
// a.p = /* string to pass to panic */;
|
||||
// crosscall2(_cgo_panic, &a, sizeof a);
|
||||
// /* The function call will not return. */
|
||||
|
||||
void runtime·_cgo_panic_internal(void);
|
||||
|
||||
#pragma cgo_export_static _cgo_panic
|
||||
#pragma cgo_export_dynamic _cgo_panic
|
||||
#pragma textflag NOSPLIT
|
||||
void
|
||||
_cgo_panic(void *a, int32 n)
|
||||
{
|
||||
runtime·cgocallback((void(*)(void))runtime·_cgo_panic_internal, a, n);
|
||||
}
|
||||
|
||||
#pragma cgo_import_static x_cgo_init
|
||||
extern void x_cgo_init(G*);
|
||||
void (*_cgo_init)(G*) = x_cgo_init;
|
||||
|
||||
#pragma cgo_import_static x_cgo_malloc
|
||||
extern void x_cgo_malloc(void*);
|
||||
void (*_cgo_malloc)(void*) = x_cgo_malloc;
|
||||
|
||||
#pragma cgo_import_static x_cgo_free
|
||||
extern void x_cgo_free(void*);
|
||||
void (*_cgo_free)(void*) = x_cgo_free;
|
||||
|
||||
#pragma cgo_import_static x_cgo_thread_start
|
||||
extern void x_cgo_thread_start(void*);
|
||||
void (*_cgo_thread_start)(void*) = x_cgo_thread_start;
|
||||
|
||||
#pragma cgo_export_static _cgo_topofstack
|
||||
#pragma cgo_export_dynamic _cgo_topofstack
|
95
src/runtime/cgo/callbacks.go
Normal file
95
src/runtime/cgo/callbacks.go
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
package cgo
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// These utility functions are available to be called from code
|
||||
// compiled with gcc via crosscall2.
|
||||
|
||||
// cgocallback is defined in runtime
|
||||
//go:linkname _runtime_cgocallback runtime.cgocallback
|
||||
func _runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
|
||||
|
||||
// The declaration of crosscall2 is:
|
||||
// void crosscall2(void (*fn)(void *, int), void *, int);
|
||||
//
|
||||
// We need to export the symbol crosscall2 in order to support
|
||||
// callbacks from shared libraries. This applies regardless of
|
||||
// linking mode.
|
||||
//go:cgo_export_static crosscall2
|
||||
//go:cgo_export_dynamic crosscall2
|
||||
|
||||
// Allocate memory. This allocates the requested number of bytes in
|
||||
// memory controlled by the Go runtime. The allocated memory will be
|
||||
// zeroed. You are responsible for ensuring that the Go garbage
|
||||
// collector can see a pointer to the allocated memory for as long as
|
||||
// it is valid, e.g., by storing a pointer in a local variable in your
|
||||
// C function, or in memory allocated by the Go runtime. If the only
|
||||
// pointers are in a C global variable or in memory allocated via
|
||||
// malloc, then the Go garbage collector may collect the memory.
|
||||
|
||||
// Call like this in code compiled with gcc:
|
||||
// struct { size_t len; void *ret; } a;
|
||||
// a.len = /* number of bytes to allocate */;
|
||||
// crosscall2(_cgo_allocate, &a, sizeof a);
|
||||
// /* Here a.ret is a pointer to the allocated memory. */
|
||||
|
||||
//go:linkname _runtime_cgo_allocate_internal runtime._cgo_allocate_internal
|
||||
var _runtime_cgo_allocate_internal byte
|
||||
|
||||
//go:linkname _cgo_allocate _cgo_allocate
|
||||
//go:cgo_export_static _cgo_allocate
|
||||
//go:cgo_export_dynamic _cgo_allocate
|
||||
//go:nosplit
|
||||
func _cgo_allocate(a unsafe.Pointer, n int32) {
|
||||
_runtime_cgocallback(unsafe.Pointer(&_runtime_cgo_allocate_internal), a, uintptr(n))
|
||||
}
|
||||
|
||||
// Panic. The argument is converted into a Go string.
|
||||
|
||||
// Call like this in code compiled with gcc:
|
||||
// struct { const char *p; } a;
|
||||
// a.p = /* string to pass to panic */;
|
||||
// crosscall2(_cgo_panic, &a, sizeof a);
|
||||
// /* The function call will not return. */
|
||||
|
||||
//go:linkname _runtime_cgo_panic_internal runtime._cgo_panic_internal
|
||||
var _runtime_cgo_panic_internal byte
|
||||
|
||||
//go:linkname _cgo_panic _cgo_panic
|
||||
//go:cgo_export_static _cgo_panic
|
||||
//go:cgo_export_dynamic _cgo_panic
|
||||
//go:nosplit
|
||||
func _cgo_panic(a unsafe.Pointer, n int32) {
|
||||
_runtime_cgocallback(unsafe.Pointer(&_runtime_cgo_panic_internal), a, uintptr(n))
|
||||
}
|
||||
|
||||
//go:cgo_import_static x_cgo_init
|
||||
//go:linkname x_cgo_init x_cgo_init
|
||||
//go:linkname _cgo_init _cgo_init
|
||||
var x_cgo_init byte
|
||||
var _cgo_init = &x_cgo_init
|
||||
|
||||
//go:cgo_import_static x_cgo_malloc
|
||||
//go:linkname x_cgo_malloc x_cgo_malloc
|
||||
//go:linkname _cgo_malloc _cgo_malloc
|
||||
var x_cgo_malloc byte
|
||||
var _cgo_malloc = &x_cgo_malloc
|
||||
|
||||
//go:cgo_import_static x_cgo_free
|
||||
//go:linkname x_cgo_free x_cgo_free
|
||||
//go:linkname _cgo_free _cgo_free
|
||||
var x_cgo_free byte
|
||||
var _cgo_free = &x_cgo_free
|
||||
|
||||
//go:cgo_import_static x_cgo_thread_start
|
||||
//go:linkname x_cgo_thread_start x_cgo_thread_start
|
||||
//go:linkname _cgo_thread_start _cgo_thread_start
|
||||
var x_cgo_thread_start byte
|
||||
var _cgo_thread_start = &x_cgo_thread_start
|
||||
|
||||
//go:cgo_export_static _cgo_topofstack
|
||||
//go:cgo_export_dynamic _cgo_topofstack
|
@ -4,16 +4,16 @@
|
||||
|
||||
// +build dragonfly
|
||||
|
||||
#include "textflag.h"
|
||||
package cgo
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
// Supply environ and __progname, because we don't
|
||||
// link against the standard DragonFly crt0.o and the
|
||||
// libc dynamic library needs them.
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
char *environ[1];
|
||||
#pragma dataflag NOPTR
|
||||
char *__progname;
|
||||
//go:linkname _environ environ
|
||||
//go:linkname _progname __progname
|
||||
|
||||
#pragma dynexport environ environ
|
||||
#pragma dynexport __progname __progname
|
||||
var _environ uintptr
|
||||
var _progname uintptr
|
@ -4,16 +4,19 @@
|
||||
|
||||
// +build freebsd
|
||||
|
||||
#include "textflag.h"
|
||||
package cgo
|
||||
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
// Supply environ and __progname, because we don't
|
||||
// link against the standard FreeBSD crt0.o and the
|
||||
// libc dynamic library needs them.
|
||||
|
||||
#pragma dataflag NOPTR
|
||||
char *environ[1];
|
||||
#pragma dataflag NOPTR
|
||||
char *__progname;
|
||||
//go:linkname _environ environ
|
||||
//go:linkname _progname __progname
|
||||
|
||||
#pragma dynexport environ environ
|
||||
#pragma dynexport __progname __progname
|
||||
//go:cgo_export_dynamic environ
|
||||
//go:cgo_export_dynamic __progname
|
||||
|
||||
var _environ uintptr
|
||||
var _progname uintptr
|
@ -9,7 +9,12 @@
|
||||
// correctly, and sometimes they break. This variable is a
|
||||
// backup: it depends only on old C style static linking rules.
|
||||
|
||||
#include "../runtime.h"
|
||||
package cgo
|
||||
|
||||
bool runtime·iscgo = 1;
|
||||
uint32 runtime·needextram = 1; // create an extra M on first cgo call
|
||||
import _ "unsafe" // for go:linkname
|
||||
|
||||
//go:linkname _iscgo runtime.iscgo
|
||||
var _iscgo bool = true
|
||||
|
||||
//go:linkname _needextram runtime.needextram
|
||||
var _needextram uint32 = 1 // create an extra M on first cgo call
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user