1#include <limits.h>2#include <stdlib.h>34#include <scc/scc.h>56#include "cc2.h"78static Swtch *list = NULL;910static Node *11swtch_if(Node *np)12{13 Type *tp;14 Swtch *swt;15 Node **cases, **bp, *tmpvar, *p;1617 swt = np->u.swtch;18 tp = &np->left->type;1920 tmpvar = tmpnode(tp, NULL);21 np->type = *tp;22 np->right = np->left;23 np->left = tmpvar;24 np->op = OASSIG;25 np->u.subop = 0;2627 cases = swt->cases;28 for (bp = cases; bp < &cases[swt->nr]; ++bp) {29 Node *eq, *tmp = tmpnode(tp, tmpvar->u.sym);3031 p = *bp;32 eq = node(OEQ);33 eq->type = *tp;34 eq->left = p->left;35 eq->right = tmp;36 *bp = NULL;3738 p->left = eq;39 p->op = OBRANCH;40 addstmt(p);41 }42 p = swtchdefault(swt);43 p->op = OJMP;44 addstmt(p);4546 free(cases);47 swt->cases = NULL;4849 return sethi(np);50}5152static Node *53swtch_dir(Node *np, long long min, long long max)54{55 int i;56 long long cur, nval;57 Swtch *swt;58 Symbol *tbl;59 Node *p, *def, **cases;6061 tbl = getsym(TMPSYM);62 tbl->kind = SLOCAL;63 tbl->type = ptrtype;64 tbl->type.flags |= INITF;65 defglobal(tbl);6667 swt = np->u.swtch;68 cases = swt->cases;6970 def = swtchdefault(swt);71 def->type = ptrtype;72 def->op = OLABEL;7374 i = 0;75 p = NULL;76 for (cur = min; cur <= max; ++cur) {77 if (!p && i < swt->nr) {78 p = cases[i++];79 p->type = ptrtype;80 p->op = OLABEL;81 nval = p->left->u.i;82 }83 if (p && nval == cur) {84 data(p);85 p = NULL;86 } else {87 data(def);88 }89 }90 endinit();9192 return np;93}9495Node *96swtch(Node *np)97{98 Swtch *swt;99 int n;100 long long min, max, range;101102 swt = np->u.swtch;103 min = swt->min;104 max = swt->max;105 range = max - min + 1;106 n = swt->nr;107108 if (n < mach.swtchif)109 return swtch_if(np);110 return swtch_dir(np, min, max);111}112113Node *114swtchdefault(Swtch *swt)115{116 Node *np;117118 np = swt->defnode;119 if (!np)120 np = swt->eswtch;121 return np;122}123124Swtch *125newswtch(Swtch *swt)126{127 Swtch *p = xmalloc(sizeof(*p));128129 *p = *swt;130 p->next = list;131 return list = p;132}133134void135cleanswtch(void)136{137 Swtch *p, *next;138 Node **bp, **cases;139140 for (p = list; p; p = next) {141 next = p->next;142 cases = p->cases;143 if (cases) {144 for (bp = cases; bp < &cases[p->nr]; ++p)145 deltree(*bp);146 free(cases);147 }148 free(p);149 }150 list = NULL;151}