scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

swtch.c (2104B)


      1 #include <limits.h>
      2 #include <stdlib.h>
      3 
      4 #include <scc/scc.h>
      5 
      6 #include "cc2.h"
      7 
      8 static Swtch *list;
      9 
     10 static Node *
     11 swtch_if(Node *np)
     12 {
     13 	Type *tp;
     14 	Swtch *swt;
     15 	Node **cases, **bp, *tmpvar, *p;
     16 
     17 	swt = np->u.swtch;
     18 	tp = &np->left->type;
     19 
     20 	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;
     26 
     27 	cases = swt->cases;
     28 	for (bp = cases; bp < &cases[swt->nr]; ++bp) {
     29 		Node *eq, *tmp = tmpnode(tp, tmpvar->u.sym);
     30 
     31 		p = *bp;
     32 		eq = node(OEQ);
     33 		eq->type = *tp;
     34 		eq->left = p->left;
     35 		eq->right = tmp;
     36 		*bp = NULL;
     37 
     38 		p->left = eq;
     39 		p->op = OBRANCH;
     40 		addstmt(p);
     41 	}
     42 	p = swtchdefault(swt);
     43 	p->op = OJMP;
     44 	addstmt(p);
     45 
     46 	free(cases);
     47 	swt->cases = NULL;
     48 
     49 	return sethi(np);
     50 }
     51 
     52 static Node *
     53 swtch_dir(Node *np, TINT min, TINT max)
     54 {
     55 	int i;
     56 	TINT cur, nval;
     57 	Swtch *swt;
     58 	Symbol *tbl;
     59 	Node *p, *def, **cases;
     60 
     61 	tbl = getsym(TMPSYM);
     62 	tbl->kind = SLOCAL;
     63 	tbl->type = ptrtype;
     64 	tbl->type.flags |= INITF;
     65 	defglobal(tbl);
     66 
     67 	swt = np->u.swtch;
     68 	cases = swt->cases;
     69 
     70 	def = swtchdefault(swt);
     71 	def->type = ptrtype;
     72 	def->op = OLABEL;
     73 
     74 	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();
     91 
     92 	return np;
     93 }
     94 
     95 Node *
     96 swtch(Node *np)
     97 {
     98 	Swtch *swt;
     99 	int n;
    100 	TINT min, max, range;
    101 
    102 	swt = np->u.swtch;
    103 	min = swt->min;
    104 	max = swt->max;
    105 	range = max - min + 1;
    106 	n = swt->nr;
    107 
    108 	if (n < mach.swtchif)
    109 		return swtch_if(np);
    110 	return swtch_dir(np, min, max);
    111 }
    112 
    113 Node *
    114 swtchdefault(Swtch *swt)
    115 {
    116 	Node *np;
    117 
    118 	np = swt->defnode;
    119 	if (!np)
    120 		np = swt->eswtch;
    121 	return np;
    122 }
    123 
    124 Swtch *
    125 newswtch(Swtch *swt)
    126 {
    127 	Swtch *p = xmalloc(sizeof(*p));
    128 
    129 	*p = *swt;
    130 	p->next = list;
    131 	return list = p;
    132 }
    133 
    134 void
    135 cleanswtch(void)
    136 {
    137 	Swtch *p, *next;
    138 	Node **bp, **cases;
    139 
    140 	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 }