diff options
author | Stefan Kempf <stefan@cvs.openbsd.org> | 2007-11-22 15:06:44 +0000 |
---|---|---|
committer | Stefan Kempf <stefan@cvs.openbsd.org> | 2007-11-22 15:06:44 +0000 |
commit | 7abafbe7948887da7ef709612930fdb77ee8eed9 (patch) | |
tree | fbfa7c7793f3e2004f9d3ce25351e32415818d6f /usr.bin/pcc | |
parent | 9f7362ac1c12b1c54bcafe0722250b9effa94b3e (diff) |
Pull from master repo:
Put the genswitch() code that is found in most backends into
the MI part. The backend version is renamed to mygenswitch()
and can provide improved translations for switch statements.
Improved implementation of the switch constraints/semantics
described in the standard.
ok ragge@, otto@
With help and comments from ragge and gmcgarry
Diffstat (limited to 'usr.bin/pcc')
-rw-r--r-- | usr.bin/pcc/ccom/cgram.y | 101 | ||||
-rw-r--r-- | usr.bin/pcc/ccom/pass1.h | 5 | ||||
-rw-r--r-- | usr.bin/pcc/ccom/trees.c | 17 | ||||
-rw-r--r-- | usr.bin/pcc/hppa/code.c | 25 | ||||
-rw-r--r-- | usr.bin/pcc/i386/code.c | 25 | ||||
-rw-r--r-- | usr.bin/pcc/m16c/code.c | 31 | ||||
-rw-r--r-- | usr.bin/pcc/mips/code.c | 25 | ||||
-rw-r--r-- | usr.bin/pcc/nova/code.c | 25 | ||||
-rw-r--r-- | usr.bin/pcc/pdp10/code.c | 26 | ||||
-rw-r--r-- | usr.bin/pcc/powerpc/code.c | 21 | ||||
-rw-r--r-- | usr.bin/pcc/vax/code.c | 14 |
11 files changed, 144 insertions, 171 deletions
diff --git a/usr.bin/pcc/ccom/cgram.y b/usr.bin/pcc/ccom/cgram.y index 10961e47eae..7cec014fb61 100644 --- a/usr.bin/pcc/ccom/cgram.y +++ b/usr.bin/pcc/ccom/cgram.y @@ -1,4 +1,4 @@ -/* $OpenBSD: cgram.y,v 1.5 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: cgram.y,v 1.6 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). @@ -169,7 +169,8 @@ static void swend(void); static void addcase(NODE *p); static void adddef(void); static void savebc(void); -static void swstart(int); +static void swstart(int, TWORD); +static void genswitch(int, TWORD, struct swents **, int); static NODE * structref(NODE *p, int f, char *name); static char *mkpstr(char *str); static struct symtab *clbrace(NODE *); @@ -863,23 +864,24 @@ forprefix: C_FOR '(' .e ';' .e ';' { switchpart: C_SWITCH '(' e ')' { NODE *p; int num; + TWORD t; savebc(); brklab = getlab(); - if ($3->n_type != INT) { - /* must cast to integer */ - p = block(NAME, NIL, NIL, INT, 0, MKSUE(INT)); - p = buildtree(CAST, p, $3); - $3 = p->n_right; - nfree(p->n_left); - nfree(p); + if (($3->n_type != BOOL && $3->n_type > ULONGLONG) || + $3->n_type < CHAR) { + uerror("switch expression must have integer " + "type"); + t = INT; + } else { + $3 = intprom($3); + t = $3->n_type; } -// ecomp( buildtree( FORCE, $3, NIL ) ); - p = tempnode(0, INT, 0, MKSUE(INT)); + p = tempnode(0, t, 0, MKSUE(t)); num = p->n_lval; ecomp(buildtree(ASSIGN, p, $3)); branch( $$ = getlab()); - swstart(num); + swstart(num, t); reached = 0; } ; @@ -1145,6 +1147,7 @@ struct swdef { struct swents *ents; /* Linked sorted list of case entries */ int nents; /* # of entries in list */ int num; /* Node value will end up in */ + TWORD type; /* Type of switch expression */ } *swpole; /* @@ -1154,6 +1157,7 @@ static void addcase(NODE *p) { struct swents **put, *w, *sw = tmpalloc(sizeof(struct swents)); + CONSZ val; p = optim(p); /* change enum to ints */ if (p->n_op != ICON || p->n_sp != NULL) { @@ -1165,19 +1169,35 @@ addcase(NODE *p) return; } + val = p->n_lval; + p = makety(p, swpole->type, 0, 0, MKSUE(swpole->type)); + if (p->n_op != ICON) + cerror("could not cast case value to type of switch " + "expression"); + if (p->n_lval != val) + werror("case expression truncated"); + sw->sval = p->n_lval; + tfree(p); put = &swpole->ents; - for (w = swpole->ents; w != NULL && w->sval < sw->sval; w = w->next) - put = &w->next; - if (w != NULL && w->sval == sw->sval) + if (ISUNSIGNED(swpole->type)) { + for (w = swpole->ents; + w != NULL && (U_CONSZ)w->sval < (U_CONSZ)sw->sval; + w = w->next) + put = &w->next; + } else { + for (w = swpole->ents; w != NULL && w->sval < sw->sval; + w = w->next) + put = &w->next; + } + if (w != NULL && w->sval == sw->sval) { uerror("duplicate case in switch"); - else { - plabel(sw->slab = getlab()); - *put = sw; - sw->next = w; - swpole->nents++; + return; } - tfree(p); + plabel(sw->slab = getlab()); + *put = sw; + sw->next = w; + swpole->nents++; } /* @@ -1195,7 +1215,7 @@ adddef(void) } static void -swstart(int num) +swstart(int num, TWORD type) { struct swdef *sw = tmpalloc(sizeof(struct swdef)); @@ -1203,6 +1223,7 @@ swstart(int num) sw->ents = NULL; sw->next = swpole; sw->num = num; + sw->type = type; swpole = sw; } @@ -1225,12 +1246,46 @@ swend(void) swp[i] = swpole->ents; swpole->ents = swpole->ents->next; } - genswitch(swpole->num, swp, swpole->nents); + genswitch(swpole->num, swpole->type, swp, swpole->nents); swpole = swpole->next; } /* + * num: tempnode the value of the switch expression is in + * type: type of the switch expression + * + * p points to an array of structures, each consisting + * of a constant value and a label. + * The first is >=0 if there is a default label; + * its value is the label number + * The entries p[1] to p[n] are the nontrivial cases + * n is the number of case statements (length of list) + */ +static void +genswitch(int num, TWORD type, struct swents **p, int n) +{ + NODE *r, *q; + int i; + + if (mygenswitch(num, type, p, n)) + return; + + /* simple switch code */ + for (i = 1; i <= n; ++i) { + /* already in 1 */ + r = tempnode(num, type, 0, MKSUE(type)); + q = block(ICON, NIL, NIL, type, 0, MKSUE(type)); + q->n_sp = NULL; + q->n_lval = p[i]->sval; + r = buildtree(NE, r, clocal(q)); + cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); + } + if (p[0]->slab > 0) + branch(p[0]->slab); +} + +/* * Declare a variable or prototype. */ static struct symtab * diff --git a/usr.bin/pcc/ccom/pass1.h b/usr.bin/pcc/ccom/pass1.h index c736b681043..052673848d2 100644 --- a/usr.bin/pcc/ccom/pass1.h +++ b/usr.bin/pcc/ccom/pass1.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pass1.h,v 1.4 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: pass1.h,v 1.5 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -177,7 +177,7 @@ struct swents { /* switch table */ CONSZ sval; /* case value */ int slab; /* associated label */ }; -void genswitch(int, struct swents **, int); +int mygenswitch(int, TWORD, struct swents **, int); extern int blevel; extern int instruct, got_type; @@ -254,6 +254,7 @@ extern NODE *btsize(TWORD, union dimfun *, struct suedef *), *tempnode(int, TWORD type, union dimfun *df, struct suedef *sue), *doacall(NODE *f, NODE *a); +NODE *intprom(NODE *); OFFSZ tsize(TWORD, union dimfun *, struct suedef *), psize(NODE *); NODE * typenode(NODE *new); diff --git a/usr.bin/pcc/ccom/trees.c b/usr.bin/pcc/ccom/trees.c index 1fa2ecc9c74..7d93e4a97d2 100644 --- a/usr.bin/pcc/ccom/trees.c +++ b/usr.bin/pcc/ccom/trees.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trees.c,v 1.9 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: trees.c,v 1.10 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -2398,3 +2398,18 @@ plabel(int label) reached = 1; /* Will this always be correct? */ send_passt(IP_DEFLAB, label); } + +/* + * Perform integer promotion on node n. + */ +NODE * +intprom(NODE *n) +{ + if ((n->n_type >= CHAR && n->n_type < INT) || n->n_type == BOOL) { + if ((n->n_type == UCHAR && MAX_UCHAR > MAX_INT) || + (n->n_type == USHORT && MAX_USHORT > MAX_INT)) + return makety(n, UNSIGNED, 0, 0, MKSUE(UNSIGNED)); + return makety(n, INT, 0, 0, MKSUE(INT)); + } + return n; +} diff --git a/usr.bin/pcc/hppa/code.c b/usr.bin/pcc/hppa/code.c index 66300335515..a3fa3381345 100644 --- a/usr.bin/pcc/hppa/code.c +++ b/usr.bin/pcc/hppa/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.1 2007/11/16 08:36:23 otto Exp $ */ +/* $OpenBSD: code.c,v 1.2 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2007 Michael Shalayeff @@ -195,28 +195,13 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - NODE *r; - int i; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); + return 0; } /* * Called with a function call with arguments as argument. diff --git a/usr.bin/pcc/i386/code.c b/usr.bin/pcc/i386/code.c index faed14036bc..6e51e853f84 100644 --- a/usr.bin/pcc/i386/code.c +++ b/usr.bin/pcc/i386/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.4 2007/11/18 17:39:55 ragge Exp $ */ +/* $OpenBSD: code.c,v 1.5 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -248,26 +248,11 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - NODE *r; - int i; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); + return 0; } diff --git a/usr.bin/pcc/m16c/code.c b/usr.bin/pcc/m16c/code.c index 2ec7f3802f8..80bcdd70cef 100644 --- a/usr.bin/pcc/m16c/code.c +++ b/usr.bin/pcc/m16c/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.2 2007/11/16 09:00:12 otto Exp $ */ +/* $OpenBSD: code.c,v 1.3 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -345,34 +345,13 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - uerror("switch() statements unsopported"); -#if 0 - int i; - char *s; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - s = (isinlining ? permalloc(40) : tmpalloc(40)); - sprintf(s, " cmpl $%lld,%%eax", p[i]->sval); - send_passt(IP_ASM, s); - s = (isinlining ? permalloc(40) : tmpalloc(40)); - sprintf(s, " je " LABFMT, p[i]->slab); - send_passt(IP_ASM, s); - } - if (p[0]->slab > 0) - branch(p[0]->slab); -#endif + return 0; } /* * Called with a function call with arguments as argument. diff --git a/usr.bin/pcc/mips/code.c b/usr.bin/pcc/mips/code.c index bbeecd96146..99847602da6 100644 --- a/usr.bin/pcc/mips/code.c +++ b/usr.bin/pcc/mips/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.2 2007/11/16 08:34:55 otto Exp $ */ +/* $OpenBSD: code.c,v 1.3 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -216,28 +216,13 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - NODE *r; - int i; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); + return 0; } static void diff --git a/usr.bin/pcc/nova/code.c b/usr.bin/pcc/nova/code.c index dfc364011da..ee390ac99a2 100644 --- a/usr.bin/pcc/nova/code.c +++ b/usr.bin/pcc/nova/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.2 2007/11/16 09:00:13 otto Exp $ */ +/* $OpenBSD: code.c,v 1.3 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2006 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -187,28 +187,13 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - NODE *r; - int i; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); + return 0; } /* * Called with a function call with arguments as argument. diff --git a/usr.bin/pcc/pdp10/code.c b/usr.bin/pcc/pdp10/code.c index d7bdcbf760d..f52f41d48f7 100644 --- a/usr.bin/pcc/pdp10/code.c +++ b/usr.bin/pcc/pdp10/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.2 2007/11/16 09:00:13 otto Exp $ */ +/* $OpenBSD: code.c,v 1.3 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -250,27 +250,11 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - NODE *r; - int i; - - /* simple switch code */ - for (i = 1; i <= n; ++i) { - /* already in 1 */ - r = tempnode(num, INT, 0, MKSUE(INT)); - r = buildtree(NE, r, bcon(p[i]->sval)); - cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab)); - } - if (p[0]->slab > 0) - branch(p[0]->slab); - + return 0; } diff --git a/usr.bin/pcc/powerpc/code.c b/usr.bin/pcc/powerpc/code.c index 5f927ffd959..0f2338da659 100644 --- a/usr.bin/pcc/powerpc/code.c +++ b/usr.bin/pcc/powerpc/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.4 2007/11/16 09:00:13 otto Exp $ */ +/* $OpenBSD: code.c,v 1.5 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -32,10 +32,12 @@ #include "pass1.h" #include "pass2.h" +#if 0 static void genswitch_simple(int num, struct swents **p, int n); static void genswitch_bintree(int num, struct swents **p, int n); static void genswitch_table(int num, struct swents **p, int n); static void genswitch_mrst(int num, struct swents **p, int n); +#endif /* * cause the alignment to become a multiple of n @@ -317,17 +319,14 @@ fldty(struct symtab *p) { } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. - * n is the number of case statemens (length of list) */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { + return 0; +#if 0 if (n == 0) { if (p[0]->sval != 0) branch(p[0]->sval); @@ -347,8 +346,10 @@ genswitch(int num, struct swents **p, int n) if (0) genswitch_bintree(num, p, n); genswitch_mrst(num, p, n); +#endif } +#if 0 static void genswitch_simple(int num, struct swents **p, int n) { @@ -808,6 +809,8 @@ mrst_find_window(struct swents **p, int n, int *state, int lab, int *len, int *l return Wmax; } +#endif + /* * Called with a function call with arguments as argument. * This is done early in buildtree() and only done once. diff --git a/usr.bin/pcc/vax/code.c b/usr.bin/pcc/vax/code.c index 8e041b69e55..a4096fd9f13 100644 --- a/usr.bin/pcc/vax/code.c +++ b/usr.bin/pcc/vax/code.c @@ -1,4 +1,4 @@ -/* $OpenBSD: code.c,v 1.3 2007/11/16 09:00:13 otto Exp $ */ +/* $OpenBSD: code.c,v 1.4 2007/11/22 15:06:43 stefan Exp $ */ /* * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. * @@ -202,17 +202,13 @@ fldty( p ) struct symtab *p; { /* fix up type of field p */ ; } -/* p points to an array of structures, each consisting - * of a constant value and a label. - * The first is >=0 if there is a default label; - * its value is the label number - * The entries p[1] to p[n] are the nontrivial cases +/* * XXX - fix genswitch. */ -void -genswitch(int num, struct swents **p, int n) +int +mygenswitch(int num, TWORD type, struct swents **p, int n) { - cerror("genswitch"); + return 0; } #ifdef notyet |