diff options
Diffstat (limited to 'utils/cc')
| -rw-r--r-- | utils/cc/cc.h | 13 | ||||
| -rw-r--r-- | utils/cc/com.c | 2 | ||||
| -rw-r--r-- | utils/cc/com64.c | 8 | ||||
| -rw-r--r-- | utils/cc/dcl.c | 20 | ||||
| -rw-r--r-- | utils/cc/dpchk.c | 49 | ||||
| -rw-r--r-- | utils/cc/lex.c | 72 | ||||
| -rw-r--r-- | utils/cc/lexbody | 6 | ||||
| -rw-r--r-- | utils/cc/mkfile | 2 | ||||
| -rw-r--r-- | utils/cc/pgen.c | 548 | ||||
| -rw-r--r-- | utils/cc/pickle.c | 2 | ||||
| -rw-r--r-- | utils/cc/pswt.c | 144 |
11 files changed, 822 insertions, 44 deletions
diff --git a/utils/cc/cc.h b/utils/cc/cc.h index d05b4397..2813d25f 100644 --- a/utils/cc/cc.h +++ b/utils/cc/cc.h @@ -121,7 +121,7 @@ struct Type long width; long offset; long lineno; - char shift; + schar shift; char nbits; char etype; char garb; @@ -317,6 +317,7 @@ enum TSTRUCT, TUNION, TENUM, + TDOT, NTYPE, TAUTO = NTYPE, @@ -329,7 +330,6 @@ enum TVOLATILE, TUNSIGNED, TSIGNED, - TDOT, TFILE, TOLD, NALLTYPES, @@ -430,6 +430,7 @@ EXTERN Type* firstargtype; EXTERN Decl* firstdcl; EXTERN int fperror; EXTERN Sym* hash[NHASH]; +EXTERN int hasdoubled; EXTERN char* hunk; EXTERN char* include[20]; EXTERN Io* iofree; @@ -473,6 +474,9 @@ EXTERN int nterm; EXTERN int packflg; EXTERN int fproundflg; EXTERN int profileflg; +EXTERN int ncontin; +EXTERN int canreach; +EXTERN int warnreach; EXTERN Bits zbits; extern char *onames[], *tnames[], *gnames[]; @@ -501,6 +505,9 @@ extern char typechlvp[]; extern char typechlp[]; extern char typechlpfd[]; +EXTERN char* typeword; +EXTERN char* typecmplx; + extern ulong thash1; extern ulong thash2; extern ulong thash3; @@ -596,7 +603,7 @@ void edecl(int, Type*, Sym*); Type* fnproto(Node*); Type* fnproto1(Node*); void markdcl(void); -Type* paramconv(Type*, int); +Type* paramconv(Type*, int, int); void pdecl(int, Type*, Sym*); Decl* push(void); Decl* push1(Sym*); diff --git a/utils/cc/com.c b/utils/cc/com.c index 558077b7..59a7bd06 100644 --- a/utils/cc/com.c +++ b/utils/cc/com.c @@ -221,6 +221,8 @@ tcomo(Node *n, int f) if(tcompat(n, l->type, r->type, tand)) goto bad; n->type = l->type; + n->right = new1(OCAST, r, Z); + n->right->type = types[TINT]; if(typeu[n->type->etype]) { if(n->op == OASASHR) n->op = OASLSHR; diff --git a/utils/cc/com64.c b/utils/cc/com64.c index 88bf11bf..e1f7c8a3 100644 --- a/utils/cc/com64.c +++ b/utils/cc/com64.c @@ -1,7 +1,7 @@ #include "cc.h" /* - * this is machine depend, but it is totally + * this is machine dependent, but it is totally * common on all of the 64-bit symulating machines. */ @@ -258,6 +258,8 @@ com64(Node *n) r->op = OFUNC; r->type = types[TLONG]; return 1; + case OCOND: + return 1; } } @@ -503,6 +505,7 @@ setvinc: n->left = a; l = new(OADDR, l, Z); l->type = typ(TIND, l->left->type); + l->complex = l->left->complex; n->right = new(OLIST, l, r); n->complex = FNX; n->op = OFUNC; @@ -536,6 +539,7 @@ setasop: t = new(OADDR, l, 0); t->type = typ(TIND, l->type); + t->complex = l->complex; r = new(OLIST, t, r); n->left = nodvasop; @@ -551,6 +555,8 @@ bool64(Node *n) { Node *n1; + if(machcap(Z)) + return; if(typev[n->type->etype]) { n1 = new(OXXX, 0, 0); *n1 = *n; diff --git a/utils/cc/dcl.c b/utils/cc/dcl.c index 71925701..6a8e7245 100644 --- a/utils/cc/dcl.c +++ b/utils/cc/dcl.c @@ -347,6 +347,10 @@ init1(Sym *s, Type *t, long o, int exflag) return Z; if(a->op == OCONST) { + if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){ + diag(a, "initialize pointer to an integer: %s", s->name); + return Z; + } if(!sametype(a->type, t)) { /* hoop jumping to save malloc */ if(nodcast == Z) @@ -537,6 +541,7 @@ suallign(Type *t) l->offset = o; } else { if(l->width <= 0) + if(l->down != T) if(l->sym) diag(Z, "incomplete structure element: %s", l->sym->name); @@ -864,7 +869,7 @@ fnproto1(Node *n) dodecl(NODECL, CXXX, n->type, n->left); t = typ(TXXX, T); if(lastdcl != T) - *t = *paramconv(lastdcl, 1); + *t = *paramconv(lastdcl, 1, 0); return t; case ONAME: @@ -970,6 +975,12 @@ rsametype(Type *t1, Type *t2, int n, int f) snap(t1); if(t2->link == T) snap(t2); + if(t1 != t2 && t1->link == T && t2->link == T){ + /* structs with missing or different tag names aren't considered equal */ + if(t1->tag == nil || t2->tag == nil || + strcmp(t1->tag->name, t2->tag->name) != 0) + return 0; + } t1 = t1->link; t2 = t2->link; for(;;) { @@ -990,7 +1001,6 @@ rsametype(Type *t1, Type *t2, int n, int f) return 1; } } - return 0; } typedef struct Typetab Typetab; @@ -1166,13 +1176,13 @@ dcllabel(Sym *s, int f) } Type* -paramconv(Type *t, int f) +paramconv(Type *t, int f, int defining) { switch(t->etype) { case TUNION: case TSTRUCT: - if(t->width <= 0) + if(t->width <= 0 && defining) diag(Z, "incomplete structure: %s", t->tag->name); break; @@ -1266,7 +1276,7 @@ pdecl(int c, Type *t, Sym *s) diag(Z, "not a parameter: %s", s->name); return; } - t = paramconv(t, c==CPARAM); + t = paramconv(t, c==CPARAM, 1); if(c == CXXX) c = CPARAM; if(c != CPARAM) { diff --git a/utils/cc/dpchk.c b/utils/cc/dpchk.c index a061b12c..011f9c8a 100644 --- a/utils/cc/dpchk.c +++ b/utils/cc/dpchk.c @@ -158,6 +158,7 @@ arginit(void) argflag('.', Fignor); argflag('#', Fignor); argflag('u', Fignor); + argflag('h', Fignor); argflag('+', Fignor); argflag('-', Fignor); @@ -444,18 +445,48 @@ void pragincomplete(void) { Sym *s; + Type *t; + int istag, w, et; + istag = 0; s = getsym(); - if(s){ - if(strcmp(s->name, "_off_") == 0) - debug['T'] = 0; - else if(strcmp(s->name, "_on_") == 0) - debug['T'] = 1; - else if(s->type == T) - diag(Z, "unknown type %s in pragma incomplete", s->name); - else - s->type->garb |= GINCOMPLETE; + 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']) diff --git a/utils/cc/lex.c b/utils/cc/lex.c index 7a99164b..8e96b7bb 100644 --- a/utils/cc/lex.c +++ b/utils/cc/lex.c @@ -7,27 +7,30 @@ /* * known debug flags - * -o file output file - * -D name define - * -I path include * -a acid declaration output - * -M constant multiplication - * -B non ANSI * -A !B + * -B non ANSI * -d print declarations - * -t print type trees - * -L print every NAME symbol - * -i print initialization + * -D name define * -F format specification check - * -r print registerization - * -v verbose printing - * -X abort on error - * -w print warnings + * -i print initialization + * -I path include + * -l generate little-endian code + * -L print every NAME symbol + * -M constant multiplication * -m print add/sub/mul trees - * -s print structure offsets (with -a or -aa) * -n print acid to file (%.c=%.acid) (with -a or -aa) + * -o file output file * -p use standard cpp ANSI preprocessor (not on windows) + * -r print registerization + * -s print structure offsets (with -a or -aa) + * -S print assembly + * -t print type trees * -V enable void* conversion warnings + * -v verbose printing + * -w print warnings + * -X abort on error + * -. Inhibit search for includes in source directory */ void @@ -54,6 +57,15 @@ main(int argc, char *argv[]) debug[c]++; break; + case 'l': /* for little-endian mips */ + if(thechar != 'v'){ + print("can only use -l with vc"); + errorexit(); + } + thechar = '0'; + thestring = "spim"; + break; + case 'o': outfile = ARGF(); break; @@ -81,7 +93,12 @@ main(int argc, char *argv[]) } if(argc > 1 && !systemtype(Windows)) { nproc = 1; - if(p = getenv("NPROC")) + /* + * if we're writing acid to standard output, don't compile + * concurrently, to avoid interleaving output. + */ + if(((!debug['a'] && !debug['Z']) || debug['n']) && + (p = getenv("NPROC")) != nil) nproc = atol(p); /* */ c = 0; nout = 0; @@ -137,6 +154,7 @@ compile(char *file, char **defs, int ndef) char ofile[400], incfile[20]; char *p, *av[100], opt[256]; int i, c, fd[2]; + static int first = 1; strcpy(ofile, file); p = utfrrune(ofile, pathchar()); @@ -146,6 +164,7 @@ compile(char *file, char **defs, int ndef) include[0] = strdup(ofile); } else p = ofile; + if(outfile == 0) { outfile = p; if(outfile) { @@ -175,21 +194,29 @@ compile(char *file, char **defs, int ndef) setinclude("/sys/include"); } } + if (first) + Binit(&diagbuf, 1, OWRITE); + /* + * if we're writing acid to standard output, don't keep scratching + * outbuf. + */ if((debug['a'] || debug['Z']) && !debug['n']) { - outfile = 0; - Binit(&outbuf, 1, OWRITE); - Binit(&diagbuf, 2, OWRITE); + if (first) { + outfile = 0; + Binit(&outbuf, dup(1, -1), OWRITE); + dup(2, 1); + } } else { c = mycreat(outfile, 0664); if(c < 0) { - diag(Z, "cannot open %s", outfile); + diag(Z, "cannot open %s - %r", outfile); outfile = 0; errorexit(); } Binit(&outbuf, c, OWRITE); - Binit(&diagbuf, 1, OWRITE); } newio(); + first = 0; /* Use an ANSI preprocessor */ if(debug['p']) { @@ -215,6 +242,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); @@ -1005,7 +1036,6 @@ getnsc(void) } c = GETC(); } - return 0; } void @@ -1123,9 +1153,11 @@ struct "for", LFOR, 0, "goto", LGOTO, 0, "if", LIF, 0, + "inline", LINLINE, 0, "int", LINT, TINT, "long", LLONG, TLONG, "register", LREGISTER, 0, + "restrict", LRESTRICT, 0, "return", LRETURN, 0, "SET", LSET, 0, "short", LSHORT, TSHORT, diff --git a/utils/cc/lexbody b/utils/cc/lexbody index d8e3f6eb..6b226ada 100644 --- a/utils/cc/lexbody +++ b/utils/cc/lexbody @@ -417,10 +417,8 @@ l1: if(c1 == '/') { for(;;) { c = GETC(); - if(c == '\n') { - lineno++; - goto l0; - } + if(c == '\n') + goto l1; if(c == EOF) { yyerror("eof in comment"); errorexit(); diff --git a/utils/cc/mkfile b/utils/cc/mkfile index c2df13a5..9a5036be 100644 --- a/utils/cc/mkfile +++ b/utils/cc/mkfile @@ -18,7 +18,7 @@ OFILES=\ scon.$O\ sub.$O\ y.tab.$O\ - machcap.$O\ + omachcap.$O\ HFILES=cc.h\ y.tab.h\ diff --git a/utils/cc/pgen.c b/utils/cc/pgen.c new file mode 100644 index 00000000..131ff012 --- /dev/null +++ b/utils/cc/pgen.c @@ -0,0 +1,548 @@ +#include "gc.h" + +void +codgen(Node *n, Node *nn) +{ + Prog *sp; + Node *n1, nod, nod1; + + cursafe = 0; + curarg = 0; + maxargsafe = 0; + hasdoubled = 0; + + /* + * isolate name + */ + for(n1 = nn;; n1 = n1->left) { + if(n1 == Z) { + diag(nn, "cant find function name"); + return; + } + if(n1->op == ONAME) + break; + } + nearln = nn->lineno; + gpseudo(ATEXT, n1->sym, nodconst(stkoff)); + sp = p; + + if(typecmplx[thisfn->link->etype]) { + if(nodret == nil) { + nodret = new(ONAME, Z, Z); + nodret->sym = slookup(".ret"); + nodret->class = CPARAM; + nodret->type = types[TIND]; + nodret->etype = TIND; + nodret = new(OIND, nodret, Z); + } + n1 = nodret->left; + if(n1->type == T || n1->type->link != thisfn->link) { + n1->type = typ(TIND, thisfn->link); + n1->etype = n1->type->etype; + nodret = new(OIND, n1, Z); + complex(nodret); + } + } + + /* + * isolate first argument + */ + if(REGARG >= 0) { + if(typecmplx[thisfn->link->etype]) { + nod1 = *nodret->left; + nodreg(&nod, &nod1, REGARG); + gmove(&nod, &nod1); + } else + if(firstarg && typeword[firstargtype->etype]) { + nod1 = znode; + nod1.op = ONAME; + nod1.sym = firstarg; + nod1.type = firstargtype; + nod1.class = CPARAM; + nod1.xoffset = align(0, firstargtype, Aarg1); + nod1.etype = firstargtype->etype; + xcom(&nod1); + nodreg(&nod, &nod1, REGARG); + gmove(&nod, &nod1); + } + } + + canreach = 1; + warnreach = 1; + gen(n); + if(canreach && thisfn->link->etype != TVOID) + warn(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' || thechar=='9' || hasdoubled) /* [sic] */ + maxargsafe = round(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; + 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]) { + nod = znode; + nod.op = OAS; + nod.left = nodret; + nod.right = l; + nod.type = n->type; + nod.complex = l->complex; + cgen(&nod, Z); + noretval(3); + gbranch(ORETURN); + break; + } + regret(&nod, n); + cgen(l, &nod); + 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) { + casf(); + 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) { + casf(); + 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(!typeword[l->type->etype] || l->type->etype == TIND) { + diag(n, "switch expression must be integer"); + break; + } + + gbranch(OGOTO); /* entry */ + sp = p; + + cn = cases; + cases = C; + casf(); + + 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); + regalloc(&nod, l, Z); + /* always signed */ + if(typev[l->type->etype]) + nod.type = types[TVLONG]; + else + nod.type = types[TLONG]; + cgen(l, &nod); + doswit(&nod); + regfree(&nod); + 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: + 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); + 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) +{ + + 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; + bool64(n); + boolgen(n, 1, Z); + return 0; +} diff --git a/utils/cc/pickle.c b/utils/cc/pickle.c index 370b9983..ef8df4c0 100644 --- a/utils/cc/pickle.c +++ b/utils/cc/pickle.c @@ -195,7 +195,7 @@ pickletype(Type *t) goto asmstr; an = pmap(s->name); - Bprint(&outbuf, "char *\npickle_%s(char *bp, char *ep, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an); + Bprint(&outbuf, "uchar*\npickle_%s(uchar *bp, uchar *ep, int un, %s *addr)\n{\n\tint _i = 0;\n\n\tUSED(_i);\n", an, an); for(l = t->link; l != T; l = l->down) picklemember(l, 0); Bprint(&outbuf, "\treturn bp;\n}\n\n"); diff --git a/utils/cc/pswt.c b/utils/cc/pswt.c new file mode 100644 index 00000000..6ef4f2fb --- /dev/null +++ b/utils/cc/pswt.c @@ -0,0 +1,144 @@ +#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; + long def, nc, i, isv; + int dup; + + 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 = (long)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 %2ld: = %.8llux\n", i, (vlong)iq[i].val); + dup = 0; + 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); + dup = 1; + } + if(dup) + return; + if(def == 0) { + def = breakpc; + nbreak++; + } + swit1(iq, nc, def, n); +} + +void +casf(void) +{ + Case *c; + + c = alloc(sizeof(*c)); + c->link = cases; + cases = c; +} + +long +outlstring(ushort *s, long n) +{ + char buf[2]; + int c; + long r; + + if(suppress) + return nstring; + while(nstring & 1) + outstring("", 1); + r = nstring; + while(n > 0) { + c = *s++; + if(align(0, types[TCHAR], Aarg1)) { + buf[0] = c>>8; + buf[1] = c; + } else { + buf[0] = c; + buf[1] = c>>8; + } + outstring(buf, 2); + n -= sizeof(ushort); + } + 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); +} + +void +ieeedtod(Ieee *ieee, double native) +{ + double fr, ho, f; + int exp; + + if(native < 0) { + ieeedtod(ieee, -native); + ieee->h |= 0x80000000L; + return; + } + if(native == 0) { + ieee->l = 0; + ieee->h = 0; + return; + } + fr = frexp(native, &exp); + f = 2097152L; /* shouldnt use fp constants here */ + fr = modf(fr*f, &ho); + ieee->h = ho; + ieee->h &= 0xfffffL; + ieee->h |= (exp+1022L) << 20; + f = 65536L; + fr = modf(fr*f, &ho); + ieee->l = ho; + ieee->l <<= 16; + ieee->l |= (long)(fr*f); +} |
