swtch.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
swtch.c (2125B)
---
1 #include <limits.h>
2 #include <stdlib.h>
3
4 #include <scc/scc.h>
5
6 #include "cc2.h"
7
8 static Swtch *list = NULL;
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 list = NULL;
151 }