summaryrefslogtreecommitdiff
path: root/utils/cc
diff options
context:
space:
mode:
Diffstat (limited to 'utils/cc')
-rw-r--r--utils/cc/acid.c4
-rw-r--r--utils/cc/cc.h28
-rw-r--r--utils/cc/cc.y30
-rw-r--r--utils/cc/com.c126
-rw-r--r--utils/cc/com64.c2
-rw-r--r--utils/cc/dcl.c10
-rw-r--r--utils/cc/dpchk.c2
-rw-r--r--utils/cc/lex.c37
-rw-r--r--utils/cc/lexbody6
-rw-r--r--utils/cc/macbody4
-rw-r--r--utils/cc/pgen.c70
-rw-r--r--utils/cc/pickle.c2
-rw-r--r--utils/cc/pswt.c85
-rw-r--r--utils/cc/scon.c4
-rw-r--r--utils/cc/sub.c38
15 files changed, 356 insertions, 92 deletions
diff --git a/utils/cc/acid.c b/utils/cc/acid.c
index 3d898883..d42b47b4 100644
--- a/utils/cc/acid.c
+++ b/utils/cc/acid.c
@@ -2,7 +2,7 @@
static char *kwd[] =
{
- "$adt", "$aggr", "$append", "$complex", "$defn",
+ "$adt", "$aggr", "$append", "$builtin", "$complex", "$defn",
"$delete", "$do", "$else", "$eval", "$head", "$if",
"$local", "$loop", "$return", "$tail", "$then",
"$union", "$whatis", "$while",
@@ -90,6 +90,8 @@ acidinit(void)
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';
}
diff --git a/utils/cc/cc.h b/utils/cc/cc.h
index 2813d25f..23b1c24b 100644
--- a/utils/cc/cc.h
+++ b/utils/cc/cc.h
@@ -17,17 +17,19 @@ typedef struct Term Term;
typedef struct Init Init;
typedef struct Bits Bits;
+typedef Rune TRune; /* target system type */
+
#define NHUNK 50000L
#define BUFSIZ 8192
-#define NSYMB 500
+#define NSYMB 1500
#define NHASH 1024
#define STRINGSZ 200
#define HISTSZ 20
-#define YYMAXDEPTH 500
+#define YYMAXDEPTH 1500
#define NTERM 10
#define MAXALIGN 7
-#define SIGN(n) ((vlong)1<<(n-1))
+#define SIGN(n) ((uvlong)1<<(n-1))
#define MASK(n) (SIGN(n)|(SIGN(n)-1))
#define BITS 5
@@ -48,7 +50,7 @@ struct Node
double fconst; /* fp constant */
vlong vconst; /* non fp const */
char* cstring; /* character string */
- ushort* rstring; /* rune string */
+ TRune* rstring; /* rune string */
Sym* sym;
Type* type;
@@ -292,6 +294,7 @@ enum
OINDEX,
OFAS,
OREGPAIR,
+ OEXREG,
OEND
};
@@ -333,6 +336,9 @@ enum
TFILE,
TOLD,
NALLTYPES,
+
+ /* adapt size of Rune to target system's size */
+ TRUNE = sizeof(TRune)==4? TUINT: TUSHORT,
};
enum
{
@@ -475,6 +481,7 @@ EXTERN int packflg;
EXTERN int fproundflg;
EXTERN int profileflg;
EXTERN int ncontin;
+EXTERN int newvlongcode;
EXTERN int canreach;
EXTERN int warnreach;
EXTERN Bits zbits;
@@ -504,6 +511,7 @@ extern char typechlv[];
extern char typechlvp[];
extern char typechlp[];
extern char typechlpfd[];
+EXTERN char* typeswitch;
EXTERN char* typeword;
EXTERN char* typecmplx;
@@ -617,7 +625,7 @@ int rsametype(Type*, Type*, int, int);
int sametype(Type*, Type*);
ulong sign(Sym*);
ulong signature(Type*);
-void suallign(Type*);
+void sualign(Type*);
void tmerge(Type*, Sym*);
void walkparam(Node*, int);
void xdecl(int, Type*, Sym*);
@@ -635,6 +643,8 @@ int tcomo(Node*, int);
int tcomx(Node*);
int tlvalue(Node*);
void constas(Node*, Type*, Type*);
+Node* uncomma(Node*);
+Node* uncomargs(Node*);
/*
* con.c
@@ -642,8 +652,8 @@ void constas(Node*, Type*, Type*);
void acom(Node*);
void acom1(vlong, Node*);
void acom2(Node*, Type*);
-int acomcmp1(const void*, const void*);
-int acomcmp2(const void*, const void*);
+int acomcmp1(void*, void*);
+int acomcmp2(void*, void*);
int addo(Node*);
void evconst(Node*);
@@ -657,6 +667,7 @@ void dclfunct(Type*, Sym*);
* sub.c
*/
void arith(Node*, int);
+int castucom(Node*);
int deadheads(Node*);
Type* dotsearch(Sym*, Type*, Node*, long*);
long dotoffset(Type*, Type*, Node*);
@@ -738,8 +749,7 @@ void gclean(void);
void gextern(Sym*, Node*, long, long);
void ginit(void);
long outstring(char*, long);
-long outlstring(ushort*, long);
-void sextern(Sym*, Node*, long, long);
+long outlstring(TRune*, long);
void xcom(Node*);
long exreg(Type*);
long align(long, Type*, int);
diff --git a/utils/cc/cc.y b/utils/cc/cc.y
index 3057547b..8c9d09b1 100644
--- a/utils/cc/cc.y
+++ b/utils/cc/cc.y
@@ -8,12 +8,14 @@
struct
{
Type* t;
- char c;
+ uchar c;
} tycl;
struct
{
Type* t1;
Type* t2;
+ Type* t3;
+ uchar c;
} tyty;
struct
{
@@ -853,9 +855,9 @@ lstring:
LLSTRING
{
$$ = new(OLSTRING, Z, Z);
- $$->type = typ(TARRAY, types[TUSHORT]);
- $$->type->width = $1.l + sizeof(ushort);
- $$->rstring = (ushort*)$1.s;
+ $$->type = typ(TARRAY, types[TRUNE]);
+ $$->type->width = $1.l + sizeof(TRune);
+ $$->rstring = (TRune*)$1.s;
$$->sym = symstring;
$$->etype = TARRAY;
$$->class = CSTATIC;
@@ -865,16 +867,16 @@ lstring:
char *s;
int n;
- n = $1->type->width - sizeof(ushort);
+ n = $1->type->width - sizeof(TRune);
s = alloc(n+$2.l+MAXALIGN);
memcpy(s, $1->rstring, n);
memcpy(s+n, $2.s, $2.l);
- *(ushort*)(s+n+$2.l) = 0;
+ *(TRune*)(s+n+$2.l) = 0;
$$ = $1;
$$->type->width += $2.l;
- $$->rstring = (ushort*)s;
+ $$->rstring = (TRune*)s;
}
zelist:
@@ -895,16 +897,22 @@ sbody:
{
$<tyty>$.t1 = strf;
$<tyty>$.t2 = strl;
+ $<tyty>$.t3 = lasttype;
+ $<tyty>$.c = lastclass;
strf = T;
strl = T;
lastbit = 0;
firstbit = 1;
+ lastclass = CXXX;
+ lasttype = T;
}
edecl '}'
{
$$ = strf;
strf = $<tyty>2.t1;
strl = $<tyty>2.t2;
+ lasttype = $<tyty>2.t3;
+ lastclass = $<tyty>2.c;
}
zctlist:
@@ -995,7 +1003,7 @@ complex:
if($$->link != T)
diag(Z, "redeclare tag: %s", $2->name);
$$->link = $4;
- suallign($$);
+ sualign($$);
}
| LSTRUCT sbody
{
@@ -1003,7 +1011,7 @@ complex:
sprint(symb, "_%d_", taggen);
$$ = dotag(lookup(), TSTRUCT, autobn);
$$->link = $2;
- suallign($$);
+ sualign($$);
}
| LUNION ltag
{
@@ -1020,7 +1028,7 @@ complex:
if($$->link != T)
diag(Z, "redeclare tag: %s", $2->name);
$$->link = $4;
- suallign($$);
+ sualign($$);
}
| LUNION sbody
{
@@ -1028,7 +1036,7 @@ complex:
sprint(symb, "_%d_", taggen);
$$ = dotag(lookup(), TUNION, autobn);
$$->link = $2;
- suallign($$);
+ sualign($$);
}
| LENUM ltag
{
diff --git a/utils/cc/com.c b/utils/cc/com.c
index 59a7bd06..3a7f29d0 100644
--- a/utils/cc/com.c
+++ b/utils/cc/com.c
@@ -1,6 +1,15 @@
#include "cc.h"
+typedef struct Com Com;
+struct Com
+{
+ int n;
+ Node *t[500];
+};
+
int compar(Node*, int);
+static void comma(Node*);
+static Node* commas(Com*, Node*);
void
complex(Node *n)
@@ -15,6 +24,8 @@ complex(Node *n)
prtree(n, "pre complex");
if(tcom(n))
return;
+ if(debug['y'] || 1)
+ comma(n);
if(debug['t'])
if(n->op != OCONST)
prtree(n, "t complex");
@@ -56,6 +67,7 @@ tcomo(Node *n, int f)
Node *l, *r;
Type *t;
int o;
+ static TRune zer;
if(n == Z) {
diag(Z, "Z in tcom");
@@ -273,8 +285,11 @@ tcomo(Node *n, int f)
goto bad;
n->type = l->type;
if(n->type->etype == TIND)
- if(n->type->link->width < 1)
- diag(n, "inc/dec of a void pointer");
+ if(n->type->link->width < 1) {
+ snap(n->type->link);
+ if(n->type->link->width < 1)
+ diag(n, "inc/dec of a void pointer");
+ }
break;
case OEQ:
@@ -610,6 +625,8 @@ tcomo(Node *n, int f)
n->addable = 1;
if(n->class == CEXREG) {
n->op = OREGISTER;
+ if(thechar == '8')
+ n->op = OEXREG;
n->reg = n->sym->offset;
n->xoffset = 0;
break;
@@ -617,10 +634,10 @@ tcomo(Node *n, int f)
break;
case OLSTRING:
- if(n->type->link != types[TUSHORT]) {
+ if(n->type->link != types[TRUNE]) {
o = outstring(0, 0);
while(o & 3) {
- outlstring(L"", sizeof(ushort));
+ outlstring(&zer, sizeof(TRune));
o = outlstring(0, 0);
}
}
@@ -882,6 +899,101 @@ tlvalue(Node *n)
}
/*
+ * hoist comma operators out of expressions
+ * (a,b) OP c => (a, b OP c)
+ * OP(a,b) => (a, OP b)
+ * a OP (b,c) => (b, a OP c)
+ */
+
+static Node*
+comargs(Com *com, Node *n)
+{
+ if(n != Z && n->op == OLIST){
+ n->left = comargs(com, n->left);
+ n->right = comargs(com, n->right);
+ }
+ return commas(com, n);
+}
+
+static Node*
+commas(Com *com, Node *n)
+{
+ Node *t;
+
+ if(n == Z)
+ return n;
+ switch(n->op){
+ case OREGISTER:
+ case OINDREG:
+ case OCONST:
+ case ONAME:
+ case OSTRING:
+ /* leaf */
+ return n;
+
+ case OCOMMA:
+ t = commas(com, n->left);
+ if(com->n >= nelem(com->t))
+ fatal(n, "comma list overflow");
+ com->t[com->n++] = t;
+ return commas(com, n->right);
+
+ case OFUNC:
+ n->left = commas(com, n->left);
+ n->right = comargs(com, n->right);
+ return n;
+
+ case OCOND:
+ n->left = commas(com, n->left);
+ comma(n->right->left);
+ comma(n->right->right);
+ return n;
+
+ case OANDAND:
+ case OOROR:
+ n->left = commas(com, n->left);
+ comma(n->right);
+ return n;
+
+ case ORETURN:
+ comma(n->left);
+ return n;
+ }
+ n->left = commas(com, n->left);
+ if(n->right != Z)
+ n->right = commas(com, n->right);
+ return n;
+}
+
+static void
+comma(Node *n)
+{
+ Com com;
+ Node *nn;
+
+ com.n = 0;
+ nn = commas(&com, n);
+ if(com.n > 0){
+if(debug['y'])print("n=%d\n", com.n);
+if(debug['y']) prtree(nn, "res");
+ if(nn != n)
+ *n = *nn;
+ while(com.n > 0){
+if(debug['y']) prtree(com.t[com.n-1], "tree");
+ nn = new1(OXXX, Z, Z);
+ *nn = *n;
+ n->op = OCOMMA;
+ n->type = nn->type;
+ n->left = com.t[--com.n];
+ n->right = nn;
+ n->lineno = n->left->lineno;
+ }
+if(debug['y']) prtree(n, "final");
+ }else if(n != nn)
+ fatal(n, "odd tree");
+}
+
+/*
* general rewrite
* (IND(ADDR x)) ==> x
* (ADDR(IND x)) ==> x
@@ -928,13 +1040,16 @@ loop:
break;
case OCAST:
+ if(castucom(n))
+ warn(n, "32-bit unsigned complement zero-extended to 64 bits");
ccom(l);
if(l->op == OCONST) {
evconst(n);
if(n->op == OCONST)
break;
}
- if(nocast(l->type, n->type)) {
+ if(nocast(l->type, n->type) &&
+ (!typefd[l->type->etype] || typeu[l->type->etype] && typeu[n->type->etype])) {
l->type = n->type;
*n = *l;
}
@@ -1342,6 +1457,7 @@ useless:
else
snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",
lt, cmps[relindex(n->op)], xbuf);
+if(debug['y']) prtree(n, "strange");
warn(n, "useless or misleading comparison: %s", cmpbuf);
return 0;
}
diff --git a/utils/cc/com64.c b/utils/cc/com64.c
index e1f7c8a3..f44a44ff 100644
--- a/utils/cc/com64.c
+++ b/utils/cc/com64.c
@@ -274,6 +274,8 @@ com64(Node *n)
case ORETURN:
case OAS:
case OIND:
+ case OLIST:
+ case OCOMMA:
return 1;
case OADD:
a = nodaddv;
diff --git a/utils/cc/dcl.c b/utils/cc/dcl.c
index 6a8e7245..c6b762a6 100644
--- a/utils/cc/dcl.c
+++ b/utils/cc/dcl.c
@@ -232,7 +232,7 @@ nextinit(void)
a->cstring++;
}
if(a->op == OLSTRING) {
- b->vconst = convvtox(*a->rstring, TUSHORT);
+ b->vconst = convvtox(*a->rstring, TRUNE);
a->rstring++;
}
a->type->width -= b->type->width;
@@ -519,7 +519,7 @@ newlist(Node *l, Node *r)
}
void
-suallign(Type *t)
+sualign(Type *t)
{
Type *l;
long o, w;
@@ -540,8 +540,8 @@ suallign(Type *t)
}
l->offset = o;
} else {
- if(l->width <= 0)
- if(l->down != T)
+ if(l->width < 0 ||
+ l->width == 0 && l->down != T)
if(l->sym)
diag(Z, "incomplete structure element: %s",
l->sym->name);
@@ -581,7 +581,7 @@ suallign(Type *t)
return;
default:
- diag(Z, "unknown type in suallign: %T", t);
+ diag(Z, "unknown type in sualign: %T", t);
break;
}
}
diff --git a/utils/cc/dpchk.c b/utils/cc/dpchk.c
index 99a49ee5..011f9c8a 100644
--- a/utils/cc/dpchk.c
+++ b/utils/cc/dpchk.c
@@ -75,9 +75,9 @@ getflag(char *s)
nstar = 0;
for(;;) {
s += chartorune(&c, s);
- fmt += runetochar(fmt, &c);
if(c == 0 || c >= nelem(flagbits))
break;
+ fmt += runetochar(fmt, &c);
f = flagbits[c];
switch(f) {
case Fnone:
diff --git a/utils/cc/lex.c b/utils/cc/lex.c
index 8ba5af5a..9aae5c2b 100644
--- a/utils/cc/lex.c
+++ b/utils/cc/lex.c
@@ -80,7 +80,8 @@ main(int argc, char *argv[])
case 'I':
p = ARGF();
- setinclude(p);
+ if(p)
+ setinclude(p);
break;
} ARGEND
if(argc < 1 && outfile == 0) {
@@ -242,14 +243,10 @@ compile(char *file, char **defs, int ndef)
close(fd[1]);
av[0] = CPP;
i = 1;
- if(debug['.']){
- sprint(opt, "-.");
- av[i++] = strdup(opt);
- }
- if(debug['+']) {
- sprint(opt, "-+");
- av[i++] = strdup(opt);
- }
+ if(debug['.'])
+ av[i++] = strdup("-.");
+ /* 1999 ANSI C requires recognising // comments */
+ av[i++] = strdup("-+");
for(c = 0; c < ndef; c++) {
sprint(opt, "-D%s", defs[c]);
av[i++] = strdup(opt);
@@ -469,7 +466,7 @@ l1:
yyerror("missing '");
peekc = c1;
}
- yylval.vval = convvtox(c, TUSHORT);
+ yylval.vval = convvtox(c, TRUNE);
return LUCONST;
}
if(c == '"') {
@@ -543,15 +540,15 @@ l1:
c = escchar('"', 1, 0);
if(c == EOF)
break;
- cp = allocn(cp, c1, sizeof(ushort));
- *(ushort*)(cp + c1) = c;
- c1 += sizeof(ushort);
+ cp = allocn(cp, c1, sizeof(TRune));
+ *(TRune*)(cp + c1) = c;
+ c1 += sizeof(TRune);
}
yylval.sval.l = c1;
do {
- cp = allocn(cp, c1, sizeof(ushort));
- *(ushort*)(cp + c1) = 0;
- c1 += sizeof(ushort);
+ cp = allocn(cp, c1, sizeof(TRune));
+ *(TRune*)(cp + c1) = 0;
+ c1 += sizeof(TRune);
} while(c1 & MAXALIGN);
yylval.sval.s = cp;
return LLSTRING;
@@ -1028,7 +1025,7 @@ getnsc(void)
} else
c = GETC();
for(;;) {
- if(!isspace(c))
+ if(c >= Runeself || !isspace(c))
return c;
if(c == '\n') {
lineno++;
@@ -1072,7 +1069,7 @@ loop:
*/
i = 2;
if(longflg)
- i = 4;
+ i = 6;
l = 0;
for(; i>0; i--) {
c = getc();
@@ -1102,7 +1099,7 @@ loop:
*/
i = 2;
if(longflg)
- i = 5;
+ i = 8;
l = c - '0';
for(; i>0; i--) {
c = getc();
@@ -1238,7 +1235,7 @@ cinit(void)
if(mygetwd(pathname, 99) == 0) {
pathname = allocn(pathname, 100, 900);
if(mygetwd(pathname, 999) == 0)
- strcpy(pathname, "/???");
+ strcpy(pathname, "/?");
}
fmtinstall('O', Oconv);
diff --git a/utils/cc/lexbody b/utils/cc/lexbody
index 6b226ada..d8e3f6eb 100644
--- a/utils/cc/lexbody
+++ b/utils/cc/lexbody
@@ -417,8 +417,10 @@ l1:
if(c1 == '/') {
for(;;) {
c = GETC();
- if(c == '\n')
- goto l1;
+ if(c == '\n') {
+ lineno++;
+ goto l0;
+ }
if(c == EOF) {
yyerror("eof in comment");
errorexit();
diff --git a/utils/cc/macbody b/utils/cc/macbody
index e26dc427..7c86bac1 100644
--- a/utils/cc/macbody
+++ b/utils/cc/macbody
@@ -25,7 +25,7 @@ getsym(void)
char *cp;
c = getnsc();
- if(!isalpha(c) && c != '_') {
+ if(!isalpha(c) && c != '_' && c < Runeself) {
unget(c);
return S;
}
@@ -33,7 +33,7 @@ getsym(void)
if(cp <= symb+NSYMB-4)
*cp++ = c;
c = getc();
- if(isalnum(c) || c == '_')
+ if(isalnum(c) || c == '_' || c >= Runeself)
continue;
unget(c);
break;
diff --git a/utils/cc/pgen.c b/utils/cc/pgen.c
index 131ff012..a5f67df2 100644
--- a/utils/cc/pgen.c
+++ b/utils/cc/pgen.c
@@ -70,8 +70,12 @@ codgen(Node *n, Node *nn)
canreach = 1;
warnreach = 1;
gen(n);
- if(canreach && thisfn->link->etype != TVOID)
- warn(Z, "no return at end of function: %s", n1->sym->name);
+ if(canreach && thisfn->link->etype != TVOID){
+ if(debug['B'])
+ warn(Z, "no return at end of function: %s", n1->sym->name);
+ else
+ diag(Z, "no return at end of function: %s", n1->sym->name);
+ }
noretval(3);
gbranch(ORETURN);
@@ -105,10 +109,20 @@ supgen(Node *n)
warnreach = owarn;
}
+Node*
+uncomma(Node *n)
+{
+ while(n != Z && n->op == OCOMMA) {
+ cgen(n->left, Z);
+ n = n->right;
+ }
+ return n;
+}
+
void
gen(Node *n)
{
- Node *l, nod;
+ Node *l, nod, rn;
Prog *sp, *spc, *spb;
Case *cn;
long sbc, scc;
@@ -129,6 +143,7 @@ loop:
case OLABEL:
case OCASE:
case OLIST:
+ case OCOMMA:
case OBREAK:
case OFOR:
case OWHILE:
@@ -151,6 +166,7 @@ loop:
break;
case OLIST:
+ case OCOMMA:
gen(n->left);
rloop:
@@ -163,7 +179,7 @@ loop:
complex(n);
if(n->type == T)
break;
- l = n->left;
+ l = uncomma(n->left);
if(l == Z) {
noretval(3);
gbranch(ORETURN);
@@ -181,6 +197,20 @@ loop:
gbranch(ORETURN);
break;
}
+ if(newvlongcode && !typefd[n->type->etype]){
+ regret(&rn, n);
+ regfree(&rn);
+ nod = znode;
+ nod.op = OAS;
+ nod.left = &rn;
+ nod.right = l;
+ nod.type = n->type;
+ nod.complex = l->complex;
+ cgen(&nod, Z);
+ noretval(2);
+ gbranch(ORETURN);
+ break;
+ }
regret(&nod, n);
cgen(l, &nod);
regfree(&nod);
@@ -241,16 +271,15 @@ loop:
complex(l);
if(l->type == T)
goto rloop;
- if(l->op == OCONST)
- if(typeword[l->type->etype] && l->type->etype != TIND) {
- casf();
- cases->val = l->vconst;
- cases->def = 0;
- cases->label = pc;
- cases->isv = typev[l->type->etype];
+ if(l->op != OCONST || !typeswitch[l->type->etype]) {
+ diag(n, "case expression must be integer constant");
goto rloop;
}
- diag(n, "case expression must be integer constant");
+ casf();
+ cases->val = l->vconst;
+ cases->def = 0;
+ cases->label = pc;
+ cases->isv = typev[l->type->etype];
goto rloop;
case OSWITCH:
@@ -258,7 +287,7 @@ loop:
complex(l);
if(l->type == T)
break;
- if(!typeword[l->type->etype] || l->type->etype == TIND) {
+ if(!typeswitch[l->type->etype]) {
diag(n, "switch expression must be integer");
break;
}
@@ -531,6 +560,8 @@ usedset(Node *n, int o)
int
bcomplex(Node *n, Node *c)
{
+ Node *b, nod;
+
complex(n);
if(n->type != T)
@@ -542,6 +573,19 @@ bcomplex(Node *n, Node *c)
}
if(c != Z && n->op == OCONST && deadheads(c))
return 1;
+ if(newvlongcode && typev[n->type->etype] && machcap(Z)) {
+ nod = znode;
+ 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];
+ xcom(b);
+ boolgen(b, 1, Z);
+ return 0;
+ }
bool64(n);
boolgen(n, 1, Z);
return 0;
diff --git a/utils/cc/pickle.c b/utils/cc/pickle.c
index ef8df4c0..1946b4e6 100644
--- a/utils/cc/pickle.c
+++ b/utils/cc/pickle.c
@@ -2,7 +2,7 @@
static char *kwd[] =
{
- "$adt", "$aggr", "$append", "$complex", "$defn",
+ "$adt", "$aggr", "$append", "$builtin", "$complex", "$defn",
"$delete", "$do", "$else", "$eval", "$head", "$if",
"$local", "$loop", "$return", "$tail", "$then",
"$union", "$whatis", "$while",
diff --git a/utils/cc/pswt.c b/utils/cc/pswt.c
index 6ef4f2fb..0471c10d 100644
--- a/utils/cc/pswt.c
+++ b/utils/cc/pswt.c
@@ -1,7 +1,7 @@
#include "gc.h"
int
-swcmp(const void *a1, const void *a2)
+swcmp(void *a1, void *a2)
{
C1 *p1, *p2;
@@ -16,8 +16,10 @@ void
doswit(Node *n)
{
Case *c;
- C1 *q, *iq;
- long def, nc, i, isv;
+ C1 *q, *iq, *iqh, *iql;
+ long def, nc, i, j, isv, nh;
+ Prog *hsb;
+ Node *vr[2];
int dup;
def = 0;
@@ -33,14 +35,20 @@ doswit(Node *n)
isv |= c->isv;
nc++;
}
- if(isv && !typev[n->type->etype])
+ if(typev[n->type->etype])
+ isv = 1;
+ else if(isv){
warn(n, "32-bit switch expression with 64-bit case constant");
+ isv = 0;
+ }
iq = alloc(nc*sizeof(C1));
q = iq;
for(c = cases; c->link != C; c = c->link) {
if(c->def)
continue;
+ if(c->isv && !isv)
+ continue; /* can never match */
q->label = c->label;
if(isv)
q->val = c->val;
@@ -49,7 +57,7 @@ doswit(Node *n)
q++;
}
qsort(iq, nc, sizeof(C1), swcmp);
- if(debug['W'])
+ if(debug['K'])
for(i=0; i<nc; i++)
print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
dup = 0;
@@ -64,7 +72,51 @@ doswit(Node *n)
def = breakpc;
nbreak++;
}
- swit1(iq, nc, def, n);
+ if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {
+ swit1(iq, nc, def, n);
+ return;
+ }
+
+ /*
+ * 64-bit case on 32-bit machine:
+ * switch on high-order words, and
+ * in each of those, switch on low-order words
+ */
+ if(n->op != OREGPAIR)
+ fatal(n, "internal: expected register pair");
+ if(thechar == '8'){ /* TO DO: need an enquiry function */
+ vr[0] = n->left; /* low */
+ vr[1] = n->right; /* high */
+ }else{
+ vr[0] = n->right;
+ vr[1] = n->left;
+ }
+ vr[0]->type = types[TLONG];
+ vr[1]->type = types[TLONG];
+ gbranch(OGOTO);
+ hsb = p;
+ iqh = alloc(nc*sizeof(C1));
+ iql = alloc(nc*sizeof(C1));
+ nh = 0;
+ for(i=0; i<nc;){
+ iqh[nh].val = iq[i].val >> 32;
+ q = iql;
+ /* iq is sorted, so equal top halves are adjacent */
+ for(j = i; j < nc; j++){
+ if((iq[j].val>>32) != iqh[nh].val)
+ break;
+ q->val = (long)iq[j].val;
+ q->label = iq[j].label;
+ q++;
+ }
+ qsort(iql, q-iql, sizeof(C1), swcmp);
+ iqh[nh].label = pc;
+ nh++;
+ swit1(iql, q-iql, def, vr[0]);
+ i = j;
+ }
+ patch(hsb, pc);
+ swit1(iqh, nh, def, vr[1]);
}
void
@@ -78,28 +130,29 @@ casf(void)
}
long
-outlstring(ushort *s, long n)
+outlstring(TRune *s, long n)
{
- char buf[2];
- int c;
+ char buf[sizeof(TRune)];
+ uint c;
+ int i;
long r;
if(suppress)
return nstring;
- while(nstring & 1)
+ while(nstring & (sizeof(TRune)-1))
outstring("", 1);
r = nstring;
while(n > 0) {
c = *s++;
if(align(0, types[TCHAR], Aarg1)) {
- buf[0] = c>>8;
- buf[1] = c;
+ for(i = 0; i < sizeof(TRune); i++)
+ buf[i] = c>>(8*(sizeof(TRune) - i - 1));
} else {
- buf[0] = c;
- buf[1] = c>>8;
+ for(i = 0; i < sizeof(TRune); i++)
+ buf[i] = c>>(8*i);
}
- outstring(buf, 2);
- n -= sizeof(ushort);
+ outstring(buf, sizeof(TRune));
+ n -= sizeof(TRune);
}
return r;
}
diff --git a/utils/cc/scon.c b/utils/cc/scon.c
index f0c2bd13..0a15885c 100644
--- a/utils/cc/scon.c
+++ b/utils/cc/scon.c
@@ -309,7 +309,7 @@ acom(Node *n)
}
int
-acomcmp1(const void *a1, const void *a2)
+acomcmp1(void *a1, void *a2)
{
vlong c1, c2;
Term *t1, *t2;
@@ -340,7 +340,7 @@ acomcmp1(const void *a1, const void *a2)
}
int
-acomcmp2(const void *a1, const void *a2)
+acomcmp2(void *a1, void *a2)
{
vlong c1, c2;
Term *t1, *t2;
diff --git a/utils/cc/sub.c b/utils/cc/sub.c
index 46e0cada..441b0c7f 100644
--- a/utils/cc/sub.c
+++ b/utils/cc/sub.c
@@ -85,7 +85,10 @@ prtree1(Node *n, int d, int f)
break;
case OLSTRING:
- print(" \"%S\"", n->rstring);
+ if(sizeof(TRune) == sizeof(Rune))
+ print(" \"%S\"", (Rune*)n->rstring);
+ else
+ print(" \"...\"");
i = 0;
break;
@@ -914,6 +917,10 @@ loop:
case ONOT:
case OADDR:
case OIND:
+ case OCOM:
+ case ONEG:
+ case OPOS:
+ case OTST:
n = n->left;
goto loop;
@@ -1187,12 +1194,15 @@ warn(Node *n, char *fmt, ...)
char buf[STRINGSZ];
va_list arg;
- if(debug['w']) {
- Bprint(&diagbuf, "warning: ");
+ if(debug['w'] || debug['W']) {
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
- Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
+ if(debug['W']) {
+ diag(n, "%s", buf);
+ return;
+ }
+ Bprint(&diagbuf, "warning: %L %s\n", (n==Z)? nearln: n->lineno, buf);
if(n != Z)
if(debug['v'])
@@ -1485,6 +1495,7 @@ Init onamesinit[] =
OINDEX, 0, "INDEX",
OFAS, 0, "FAS",
OREGPAIR, 0, "REGPAIR",
+ OEXREG, 0, "EXREG",
OEND, 0, "END",
-1, 0, 0,
};
@@ -1951,6 +1962,7 @@ tinit(void)
/* 32-bit defaults */
typeword = typechlp;
+ typeswitch = typechl;
typecmplx = typesuv;
}
@@ -2022,3 +2034,21 @@ mixedasop(Type *l, Type *r)
{
return !typefd[l->etype] && typefd[r->etype];
}
+
+
+/*
+ * (uvlong)~ul creates a ul mask with top bits zero, which is usually wrong
+ * an explicit cast to ulong after ~ suppresses the diagnostic
+ */
+int
+castucom(Node *r)
+{
+ Node *rl;
+
+ if(r->op == OCAST &&
+ (rl = r->left)->op == OCOM &&
+ (r->type->etype == TVLONG || r->type->etype == TUVLONG) &&
+ typeu[rl->type->etype] && typechl[rl->type->etype])
+ return 1;
+ return 0;
+}