[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:
Russ Cox 2014-11-15 08:00:38 -05:00
commit 0fcf54b3d2
384 changed files with 22419 additions and 69497 deletions

0
dev.cc Normal file
View File

View File

@ -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;

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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");
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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");
}
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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')
;
}

View File

@ -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;

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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,

View File

@ -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
View File

@ -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",

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
View 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
)

View 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
View 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
)

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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
View 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)

View File

@ -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;
}

View 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)

View File

@ -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
View 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
)

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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